home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / hamradio / ax25_30.zip / AX25_30.PAS
Pascal/Delphi Source File  |  1994-10-10  |  81KB  |  2,926 lines

  1. "6809"
  2. $RECURSIVE OFF$
  3. $SEPARATE ON$
  4. $EXTENSIONS ON$
  5. $GLOBPROC ON$
  6.  
  7. {*****************************************************************
  8.  
  9.      COPYRIGHT, (C) DAVID GEORGE HENDERSON III
  10.             HAROLD E. PRICE, 1982, 1983
  11.  
  12.      Permission is granted for use so long as this notice of
  13.      authorship is retained in the source code.
  14.  
  15. ******************************************************************}
  16.  
  17. { Implementation notes:
  18.  
  19.      Great pains have been taken to make this software as
  20.      transportable as possible.  The use of sub-sets and character
  21.      strings have been specifically avoided.  When modifying this
  22.      software, please keep that goal in mind.
  23.  
  24.      The code also contains several kludges designed to avoid
  25.      bugs/limitations in the HP64000 compiler which was used to
  26.      produce the BETA version of the TAPR TNC.    These primarily
  27.      occur in lines using the variables KLUDGE and W8FIX.
  28.  
  29.      The WRITEn routines exist to improve transportability
  30.      between various versions of PASCAL used during the initial
  31.      testing.  Please attempt to use them when adding new features.
  32.  
  33.      The HP64000 PASCAL seems to have a problem with
  34.      IF NOT simple_boolean THEN.  They have been changed to
  35.      IF simple_boolean = FALSE THEN
  36.  
  37.  
  38.                   Harold E. Price, NK6K
  39.                   David G. Henderson, KD4NL
  40.  
  41.                   Los Angeles, December 1982.
  42.  
  43. Changes made September 1983, DGH.
  44.  
  45.  1. Ten calls in header implies up to 8 digipeats.
  46.  2. Low level routine LLRINF now called with link state on change.
  47.  3. Tracebit MONDIGI added. Forces all digipeated IFRAMES and UI frames to be monitored.
  48.  4. Tracebit DUMPDIGI added. Dumps all digipeated frames if not already monitored.
  49.  5. Automatic switchover to Vancouver mode removed. No more 'Vancouver virus'.
  50.  6. If a frame is monitored, it won't be shown as normal data.
  51.  7. The NEW parameter now has no meaning. Left in command table for debug operations.
  52.  8. DM now sent in AX25 when the TNC is not idle and a SABM is received from a foreign station.
  53.  9. '*** <call> busy' shows up on the station trying to connect to the busy station.
  54. 10. '*** CONNECT REQUEST: <CALL>' shows up on the busy station if not transparent.
  55. 11. Poll/Final bit usage:  Will never send poll bit on timeout, never needs
  56.     final bit for timer recovery. When a poll bit is received in an IFRAME,
  57.     then one of RNR|REJ|RR with the final bit set is forced even if a
  58.     piggyback ack could be used.  The poll/final bit is always ignored
  59.     in Vancouver mode.
  60.  
  61.     This action can be disable with a trace bit.
  62.  
  63. WARNING: These changes must be made in other modules for this source!!!!!
  64. 1. The changed state table is kept in Pascal comments in the ROSEG declaration.
  65. 2. A 'BUSY' message has been added to the end of ROSEG.
  66.  
  67. Changes made October 1983  HEP.
  68.  
  69. 1. MON flags moved to novram.  MTO/MFROM ALL construct was
  70.    given a ghost flag in novram.
  71.  
  72. 2. Parser error of blank line removed.
  73.  
  74. 3. CWID ON|OFF and IDTEXT [text] added.
  75.  
  76. 4.  Full duplex command added
  77. }
  78.  
  79. PROGRAM AX25MAIN;
  80.  
  81. CONST
  82.       XPIDBYTE = 240; { transmitted PID byte }
  83.       MODULO = 8;
  84.       MAXFRAME = 296;
  85.       PROMPTLEN = 4;
  86.       BUFRSIZE = 256;
  87.       NUMHDCALL =10 { max number of calls in header };
  88.       NHEADCH = 6; { kludge... number of header call characters }
  89.       NHEADSIZE = 7; { length of call with SSID byte }
  90.       TOCALLX = 1;
  91.       FRCALLX = 2;
  92.       RPCALLX = 3;
  93.  
  94. TYPE
  95.      CH6 = { packed } ARRAY[1..6] OF CHAR;
  96.      CH6X = { packed } ARRAY[1..NHEADCH] OF CHAR;
  97.      CH7 = { packed } ARRAY [1..7] OF CHAR;
  98.      CH128 = { packed } ARRAY [1..128] OF CHAR;
  99.      CH4096 = { packed } ARRAY[1..4096] OF CHAR;
  100.      CH5 = { packed } ARRAY[1..5] OF CHAR;
  101.      CH8 = { packed } ARRAY[1..8] OF CHAR;
  102.      CH10 = { packed } ARRAY[1..10] OF CHAR;
  103.      CH15 = { packed } ARRAY[1..15] OF CHAR;
  104.      CH20 = { packed } ARRAY[1..20] OF CHAR;
  105.  
  106.      FTYPE = (F_NULL, F_CON, F_DISC);
  107.      LIT_TYPE = (L_FNULL, { must be first }
  108.          L_AFTER,
  109.          L_ALL,
  110.          L_CHAR,
  111.          L_CONVERS,
  112.          L_EVERY,
  113.          L_ID,
  114.          L_LINK,
  115.          L_OFF,
  116.          L_ON,
  117.          L_MONITOR,
  118.          L_NO,
  119.          L_NONE,
  120.          L_TERMINAL,
  121.          L_TIMING,
  122.          L_TRANS,
  123.          L_VIA,
  124.          L_YES,
  125.          L_LNULL); { must be last }
  126. { various commands that this system will accept }
  127.      COM_TYPE = (C_FNULL, { must be first }
  128.          C_ABAUD,
  129.          C_ABIT,
  130.          C_AUTOLF,
  131.          C_AWLEN,
  132.          C_AX25,
  133.          C_AXDELAY,
  134.          C_AXHANG,
  135.          C_BEACON,
  136.          C_BKONDEL,
  137.          C_BTEXT,
  138.          C_CONNECT,
  139.          C_CALIBRAT,
  140.          C_CANLINE,
  141.          C_CANPAC,
  142.          C_CMDTIME,
  143.          C_COMMAND,
  144.          C_CONMODE,
  145.          C_CONOK,
  146.          C_CONVERS,
  147.          C_CPACTIME,
  148.          C_CR,
  149.          C_CWID,
  150.          C_DISCONNE,
  151.          C_DEBUG,
  152.          C_DELETE,
  153.          C_DIGIPEAT,
  154.          C_DISPLAY,
  155.          C_DWAIT,
  156.          C_ECHO,
  157.          C_ESCAPE,
  158.          C_FLOW,
  159.          C_FRACK,
  160.          C_FULLDUP,
  161.          C_TRANS,
  162.          C_HBAUD,
  163.          C_ID,
  164.          C_IDTEXT,
  165.          C_LCOK,
  166.          C_LFADD,
  167.          C_MONITOR,
  168.          C_MONALL,
  169.          C_MAXFRAME,
  170.          C_MONCON,
  171.          C_MONFROM,
  172.          C_MONTO,
  173.          C_MYCALL,
  174.          C_MYVADR,
  175.          C_NULLS,
  176.          C_NUCR,
  177.          C_NULF,
  178.          C_PACLEN,
  179.          C_PACTIME,
  180.          C_PARITY,
  181.          C_PASS,
  182.          C_PERM,
  183.          C_PROGRAM,
  184.          C_RESET,
  185.          C_REDISP,
  186.          C_RETRY,
  187.          C_SCREENL,
  188.          C_SENDPAC,
  189.          C_START,
  190.          C_STOP,
  191.          C_TRACE,
  192.          C_TXDELAY,
  193.          C_TXFLOW,
  194.          C_UNPROTO,
  195.          C_VDIGIPEA,
  196.          C_VRPT,
  197.          C_XFLOW,
  198.          C_XMITOK,
  199.          C_XOFF,
  200.          C_XON,
  201.          C_LNULL); { must be last }
  202.      BUFTYPE = { packed } ARRAY [1..BUFRSIZE] OF CHAR;
  203.      BAUDTYPE = ARRAY [0..15] OF INTEGER;
  204.      HEADCALL = { packed } RECORD
  205.                CALL: CH6X;
  206.                SSID: CHAR;
  207.         END { RECORD };
  208.      POSHEAD = (CHARRAY,VANCHD,AX25HD);
  209.      VANTYPE =     RECORD
  210.               VANID: CHAR;
  211.               VANCTL: CHAR;
  212.               FRCALL: CH6X;
  213.               TOCALL: CH6X;
  214.            END { RECORD };
  215.      HEADTYPE = RECORD
  216.            CASE POSHDJUNK:POSHEAD OF
  217.               CHARRAY: (CH: { packed } ARRAY[0..35]OF CHAR);
  218.               VANCHD: (VANCHEAD: VANTYPE);
  219.               AX25HD: (CALLS: { packed } ARRAY[1..NUMHDCALL] OF
  220.                    HEADCALL);
  221.         END { CASE };
  222. { States the link may be in. These are exactly the same states
  223.   with exactly the same meanings as in the BX.25 document from AT&T.
  224.   Vancouver mode uses all the states except LS3. Events are altered in
  225.   this mode to reflect the sending of CONREQ,CONACK,DISREQ,DISACK }
  226.  
  227.      LSTYPE = (LS1, { idle,disconnected }
  228.            LS2, { link setup, sending SABMs trying to get connected }
  229.            LS3, { frame rejected, I need to send FRMR and get UA }
  230.            LS4, { disconnect request, sending DISC and looking for UA }
  231.            LS5);{ information transfer. connedted & exchanging messages }
  232.  
  233. { Events that may happen  Some code depends on the order of events,
  234.   and all possible types of frames are events. }
  235.      EVTYPE = (OTHERFR, {0}
  236.            IFRAME,    {1}
  237.            RR,    {2}
  238.            RNR,    {3}
  239.            REJ,    {4}
  240.            UI,    {5}
  241.            SABM,    {6}
  242.            DISC,    {7}
  243.            DM,    {8}
  244.            UA,    {9}
  245.            FRMR,    {10}
  246.            T1RO,    {11}
  247.            N2EXCEED,{12}
  248.            DISREQ,    {13}
  249.            DISACK,    {14}
  250.            CONREQ,    {15}
  251.            CONACK    {16});
  252.  
  253. { Actions that may have to be taken as a result of event/state combos }
  254.      CNCACT = (NOP_CNC,    {0}
  255.            UA_S5_CNC,  {1}
  256.            DM_CNC,       {2}
  257.            UA_CNC,       {3}
  258.            DM_S1_CNC,  {4}
  259.            UA_S1_CNC,  {5}
  260.            M_S5_CNC,   {6}
  261.            M_S1_CNC,   {7}
  262.            SABM_S2_CNC,{8}
  263.            FRMR_CNC,   {9}
  264.            DISC_CNC,   {10}
  265.            SABM_CNC,   {11}
  266.            CONR_CNC,   {12}
  267.            CONA_CNC,   {13}
  268.            DISR_CNC,   {14}
  269.            DISA_CNC,   {15}
  270.            BAILOUT_CNC,{16}
  271.            SAYBUSY_CNC){17};
  272.  
  273. { Meaning of bits that can be set via TRACE command }
  274.      TRACEBIT = (DUMPFRAME, { x1xx dump all incoming frames }
  275.          DUMPSTATE, { x2xx show before, after in state change routine}
  276.          DUMPIFRAME, { x4xx incoming frames that look useful }
  277.          DUMPOFRAME, { x8xx dump outgoing frames }
  278.          DUMPFRMR, { 1xxx dump FRMR stuff, in and out }
  279.          DUMPALLD, { 2xxx dump data as well as header }
  280.          DUMPJUNK1,{ 4xxx spacer (full dup now command) }
  281.          DUMPJUNK2, { 8xxx spacer }
  282.          DUMPJUNK3, { xxx1 spacer }
  283.          DUMPJUNK4, { xxx2 spacer }
  284.          DUMPJUNK5, { xxx4 spacer }
  285.          DUMPJUNK6, { xxx8 spacer }
  286.          DUMPJUNK7, { xx1x spacer }
  287.          MONDIGI, { xx2x allow digipeated frames to get monitored }
  288.          DUMPDIGI, { xx4x dump any digipeated frames that dont get monitored }
  289.          DONTFINL); { xx8x never send the final bit }
  290.      TIMER = RECORD
  291.          RUNNING,PENDING: BOOLEAN;
  292.          TSTOP: INTEGER;
  293.          END;
  294.      FRCHTYPE = { packed } ARRAY[0..MAXFRAME] OF CHAR;
  295.  
  296.      MONLIST = RECORD
  297.           CNT: 0..NUMHDCALL; { number of calls in list }
  298.           ALL: BOOLEAN; { when CNT = 0; TRUE = all calls, FALSE = no calls }
  299.           CALLS: HEADTYPE;
  300.            END { RECORD };
  301.  
  302.      ACTYPE = RECORD { assembler communications area }
  303. { beginning of EEPROM data }
  304.  
  305.          LFADD: BOOLEAN;   { add LF in outgoing packet after CR }
  306.          NUCR: BOOLEAN;  { send nulls after CR }
  307.          NULF: BOOLEAN;  { send nulls after LF }
  308.          ESCAPE: BOOLEAN;  { Print $ for escape }
  309.          LCOK: BOOLEAN;    { Don't translate lower to upper on display }
  310.          BKONDEL: BOOLEAN; { Backspace when delete character entered}
  311.          ECHO: BOOLEAN;    { Echo terminal input characters }
  312.          AUTOLF: BOOLEAN;  { insert LF after CR on display }
  313.  
  314.          XFLOW: BOOLEAN; { set for XON/XOFF, reset for hardware only }
  315.          FLOW: BOOLEAN; { flow control }
  316.          DELCHR: BOOLEAN; { delete character }
  317.          RPTOK: BOOLEAN;  { be an AX.25 digipeater }
  318.          VANCDP: BOOLEAN; { OK to be a Vancouver digipeater }
  319.          CONOK: BOOLEAN; { OK to connect }
  320.          XMITOK: BOOLEAN; { OK to transmit }
  321.          AX25: BOOLEAN; { originate AX.25; reset means Vancouver }
  322.  
  323.          PCEVY: BOOLEAN; { packet timeout EVERY or AFTER }
  324.          CONMODE: BOOLEAN; { auto connect mode default }
  325.          VRPT: BOOLEAN; { VDIGIPEAT this packet }
  326.          CR: BOOLEAN;  { insert SENDPAC at end of CONVERS packet }
  327.          CPT: BOOLEAN; { use PACTIME in CONVERSE }
  328.          TXF: BOOLEAN; { use XFLOW in TRANSPARENT }
  329.          CWID: BOOLEAN; { CWID every 9.5 min if set }
  330.          BECEVY: BOOLEAN;  { beacon every (set) or after (reset) }
  331.  
  332.          FULLDUP: BOOLEAN; { assume full duplex link }
  333.          MONON: BOOLEAN; { monitor mode on }
  334.          MONCON: BOOLEAN; { monitor while connected }
  335.          MONALL: BOOLEAN; { monitor others' connected frames }
  336.          MONTO: BOOLEAN; { set equal to MON.TOLIST.ALL }
  337.          MONFROM: BOOLEAN; {set equal to MON.FROMLIST.ALL }
  338.  
  339.          SCWID: INTEGER; { screen width }
  340.          PLEN: INTEGER;  { packet data length }
  341.          XTRA: CHAR; { space filler }
  342.  
  343.          CLCHR: CHAR; { cancel line character }
  344.          CPCHR: CHAR; { cancel packet character }
  345.          STPCHR: CHAR; { stop character from terminal }
  346.          STRCHR: CHAR; { start character from terminal }
  347.  
  348.          PASCHR: CHAR; { pass-character character }
  349.          RDSCHR: CHAR; { redispaly-line character }
  350.          SPCHR: CHAR; { send-packet character }
  351.          CMDCHR: CHAR; { command-mode character }
  352.  
  353.          DBGCHR: CHAR;    { enter-debug mode character }
  354.          XFFCHR: CHAR; { stop character from TNC }
  355.          XONCHR: CHAR; { start character from TNC }
  356.          VANID: CHAR; { Vancouver address }
  357.  
  358.          MYCALL: HEADCALL; { call sign of this TNC, extension in 7th byte }
  359.  
  360.          KV7D: CHAR; { dummy byte }
  361.          HBAUD: INTEGER; { HDLC baud rate }
  362.          NULLS: INTEGER; { number of nulls*2 after a <cr> or <lf> }
  363.          RETRY: INTEGER; { packet retry count }
  364.          IFTIME: INTEGER; { frame timeout time for retry }
  365.          KMAX: INTEGER;  { max frames in flight }
  366.  
  367.          TXDLY: INTEGER; { transmit keyup delay }
  368.          AXDLY: INTEGER; { audio repeater keyup delay }
  369.          AXHANG: INTEGER; { audio repeater hang time }
  370.          PCTIME: INTEGER; { packet timeout time for transparent mode }
  371.          CMTIME: INTEGER; { command timeout value for transparent mode }
  372.          DWAIT: INTEGER; { digipeat wait time }
  373.  
  374.          BECTIM: INTEGER; { beacon time }
  375.          ABAUD: INTEGER; { terminal baud rate }
  376.          ABIT: INTEGER;   { number of stop bits }
  377.          AWLEN: INTEGER; { Word length }
  378.          PARITY: INTEGER; { Terminal parity }
  379. { end of EEPROM data }
  380.  
  381.          AIRP: INTEGER; { termainl input removal pointer }
  382.          CBPRES: BOOLEAN; { command buffer present }
  383.          HOFC: INTEGER; { number of bytes available for frame }
  384.          AOFC: INTEGER; { terminal output free count }
  385.          BECLEN: INTEGER; { BTEXT length }
  386.  
  387.          IDLEN: INTEGER; { alternate CWID length }
  388.          TICKER: INTEGER; { gets incremented every clock tick }
  389.          DCDDRP: BOOLEAN; { set when DCD drops }
  390.          DCD: BOOLEAN; { actual modem signal itself }
  391.          DIGOUT: BOOLEAN; { set when sending digipeat frame }
  392.          RETOUT: BOOLEAN; { set when retrying frame }
  393.  
  394.          HITSZ: INTEGER; { HDLC input top size -- number of bytes in top frame }
  395.  
  396.          MODEF1: BOOLEAN; { TRUE = command mode, FALSE = other }
  397.          MODEF2: BOOLEAN; { TRUE = converse mode, FALSE = transparent mode }
  398.          HACT: BOOLEAN; { set when HDLC frames are present in the output queue }
  399.          T1,TBEACON: TIMER;
  400.          UCONCNT: INTEGER; { unconnected list size }
  401.           END;
  402.  
  403.    ACTYPEY= RECORD
  404.          BECTXT: CH128;  { BEACON text string }
  405.          IDTXT: CH128;    { alternate CWID text }
  406.         END;
  407.  
  408.  
  409.      STATEVAR = 0..7;
  410.      FLMARK = RECORD
  411.          RP: INTEGER; { removal poineter in terminal ring buffer }
  412.          CNT: INTEGER; { count of data characters in this frame }
  413.           END { FLMARK };
  414.      POSFRAME = 1..4;
  415.      FRTYPE =     RECORD
  416.               CASE IIII:POSFRAME OF
  417.                  1: (FRVAN: VANTYPE);
  418.                  2: (CH: FRCHTYPE);
  419.                  3: (CALLS: { packed } ARRAY[1..NUMHDCALL] OF HEADCALL);
  420.                  4: (DMRHEAD: HEADTYPE; { kludge to send DM when busy });
  421.  
  422.           END { RECORD };
  423.  
  424.      ROTYPE = RECORD
  425.          COMTEXT: ARRAY[1..74] OF CH8;
  426.          LITTEXT: ARRAY[1..17] OF CH8;
  427.          HEXCHAR: { packed } ARRAY[1..16] OF CHAR;
  428.          ABAUD: BAUDTYPE;
  429.          HBAUD: BAUDTYPE;
  430.          MSG: RECORD
  431.              EH: CH5; { init 'EH?  ' }
  432.              ON: CH5; { init ' ON  ' }
  433.              OFF: CH5; { init ' OFF ' }
  434.              WAS: CH5; { init 'was    ' }
  435.              PROMPT: CH5; { init 'cmd: ' }
  436.              LINKSTATE: CH15; { init 'Link state is: ' }
  437.              DISCON: CH15; { init 'DISCONNECTED   ' }
  438.              CONTO: CH15; { init 'CONNECTED to   ' }
  439.              CANTCON: CH15; { init 'Can''t CONNECT, ' }
  440.              IGNORED: CH15; { init 'Input ignored' }
  441.              VALUEOUT: CH20; { init 'Value out of range  ' }
  442.              CONINPROG: CH20; { init 'CONNECT in progress ' }
  443.              FRMRINPROG: CH20; { init 'FRMR in progress    ' }
  444.              DISCINPROG: CH20; { init 'DISC in progress    ' }
  445.              CANTDISC: CH20; { init 'Can''t DISCONNECT,   '}
  446.              NOTWHILE: CH20; { init 'not while connedted  '}
  447.               END;
  448.          CNCACTION: ARRAY[LSTYPE,SABM..N2EXCEED,BOOLEAN] OF CNCACT;
  449.         { 13,1,0,2,0,0,0,0
  450.           0,0,12,8,0,0,13,3
  451.           15,4,0,17,6,6,0,5
  452.           12,11,16,16,0,1,0,0
  453.           0,0,0,8,0,8,0,9
  454.           16,16,0,2,15,3,7,7
  455.           0,7,0,0,14,10,16,16
  456.           13,1,15,5,0,0,0,8
  457.           0,8,0,0,16,16 }
  458.          VANCMAP: ARRAY[DISREQ..CONACK] OF EVTYPE;
  459.         { 7,8,6,9 }
  460.          TICKSPS: INTEGER; { number of clock ticks per second }
  461.          ZEROVAR: INTEGER; { always zero }
  462.          TITLERDFR: CH10; { init 'frame read' }
  463.          TITLEUSFR: CH10; { init 'frame used' }
  464.          TITLEOUTFR: CH10; { init 'frame sent' }
  465.          STATEMOD: CH10; { init 'state mod:' }
  466.          RETRYZERO: CH20; { init 'retry count exceeded' }
  467.          CONRQMSG: CH20; { init '*** connect request:' }
  468.          FRMRSENT: CH10; { init 'FRMR sent ' }
  469.          FRMRRCVD: CH10; { init 'FRMR rcvd' }
  470.          BEACON: CH6X; { init 'BEACON' }
  471.          CQ: CH6X; { init 'CQ     ' }
  472.          BUSYMSG: CH5; { init ' BUSY' }
  473.           END;
  474.  
  475. VAR
  476.  
  477.     $EXTVAR ON$
  478.     ROEXTVAR: ROTYPE;
  479.     ACX: ACTYPE;
  480.     ACY: ACTYPEY;
  481.     MON: RECORD
  482.         FRLIST: MONLIST;
  483.         TOLIST: MONLIST;
  484.      END { monitor structure };
  485.     $EXTVAR OFF$
  486.  
  487. { globasl required by parser to be in outer block }
  488.     $GLOBVAR ON$
  489.     CONCALL: HEADCALL;
  490.     CNCCALL: HEADTYPE;
  491.     NMODEF2: BOOLEAN; { TRUE = converse mode, FALSE = transparent mode }
  492.     CNCCNT: 0..NUMHDCALL;
  493.     TRACEDATA: RECORD
  494.           CASE BJUNK:BOOLEAN OF
  495.              FALSE: (BITS: SET OF TRACEBIT);
  496.              TRUE: (NUMBR: INTEGER);
  497.            END { RECORD };
  498.     UCONLST: HEADTYPE; { unconnected call list }
  499.  
  500. { All of these variables are necessary to keep track of one link state }
  501.     RETRY_SIP: BOOLEAN; { set when retry send of I frames happening }
  502.     RETRY_SEQ: INTEGER; { If RETRY_SIP, then last frame sequence number for retry }
  503.     FLFIRST: INTEGER; { index of first frame in flight }
  504.     FLCUR: INTEGER; { number of frame to be send next }
  505.     FLNEXT: INTEGER; { index of next frame to be constructed }
  506.     NR: INTEGER; { next sequence number expected from other side }
  507.  
  508.     RETRYCNT: -1..127;
  509.     XRETRY: -1..127; { -1 means do it forever }
  510.  
  511.     LS: LSTYPE;
  512.     CONHEAD: HEADTYPE;
  513.     CONHDSIZE: INTEGER;
  514.     OFRMRBUF: ARRAY[1..8] OF CHAR; { outgoing FRMR frame information field }
  515.  
  516.     SENDRNR,RCVDRNR,SENDREJ,SENDRR,SENDFIN: BOOLEAN;
  517.     RNRSIZE: INTEGER;
  518.  
  519.     FLINFO: ARRAY[STATEVAR] OF FLMARK;
  520.     REMVANID: INTEGER; { Vancouver protocol ID number of other guy if connected }
  521.     PARSERES: FTYPE;
  522.     TICKTEMP: INTEGER; { avoids overflow problems in timer manipulation }
  523.     LASTCALL: INTEGER;
  524.  
  525.     $GLOBVAR OFF$
  526.  
  527.  
  528. PROCEDURE FLSHAI(VAR RP: INTEGER);
  529. EXTERNAL;
  530.  
  531. PROCEDURE GETAI(VAR RP: INTEGER; VAR N: INTEGER; VAR A: FRCHTYPE; VAR X: INTEGER);
  532. EXTERNAL;
  533.  
  534. PROCEDURE WRAPAI(VAR OLDRP: INTEGER; { input }
  535.          VAR N: INTEGER; VAR NEWRP: INTEGER { output });
  536. EXTERNAL;
  537.  
  538. PROCEDURE PUTAO(VAR A: FRCHTYPE; VAR X: INTEGER; VAR N: INTEGER);
  539. EXTERNAL;
  540.  
  541. PROCEDURE GETHI(VAR C: FRCHTYPE; VAR N: INTEGER);
  542. EXTERNAL;
  543.  
  544. PROCEDURE PUTHO(VAR A: FRCHTYPE; VAR N: INTEGER);
  545. EXTERNAL;
  546.  
  547. PROCEDURE CALIBR;
  548. EXTERNAL;
  549.  
  550. PROCEDURE PROGRM;
  551. EXTERNAL;
  552.  
  553. PROCEDURE CWID;
  554. EXTERNAL;
  555.  
  556. PROCEDURE RESET1;
  557. EXTERNAL;
  558.  
  559. PROCEDURE PUTNV; { repack NOVRAM, no burn }
  560. EXTERNAL;
  561.  
  562. PROCEDURE PUTNVB;  { repack NOVRAM and burn it }
  563. EXTERNAL;
  564.  
  565. PROCEDURE GETCMD (VAR BUF: BUFTYPE; VAR ARS: INTEGER);
  566. EXTERNAL;
  567.  
  568. PROCEDURE SETMOD;
  569. EXTERNAL;
  570.  
  571. PROCEDURE CALCFC;
  572. EXTERNAL;
  573.  
  574. PROCEDURE LLRINF(LS: INTEGER);
  575. EXTERNAL;
  576.  
  577. {
  578. PROCEDURE HDLCABORT;
  579. EXTERNAL;
  580. }
  581.  
  582. PROCEDURE REALAX25;
  583. FORWARD;
  584.  
  585. PROCEDURE AX25;
  586. BEGIN
  587. REALAX25;
  588. END;
  589.  
  590. { This set of procedures exists to increase the transportability
  591.   of the Pascal portion of the AX.25 code }
  592.  
  593. PROCEDURE WRITE5(VAR C: CH5; J: INTEGER);
  594. EXTERNAL;
  595.  
  596. PROCEDURE WRITE8(VAR C: CH8; J: INTEGER);
  597. EXTERNAL;
  598.  
  599. PROCEDURE WRITE10(VAR C: CH10; J: INTEGER);
  600. EXTERNAL;
  601.  
  602. PROCEDURE WRITE15(VAR C: CH15; J: INTEGER);
  603. EXTERNAL;
  604.  
  605. PROCEDURE WRITE20(VAR C: CH20; J: INTEGER);
  606. EXTERNAL;
  607.  
  608. PROCEDURE WRITE128(VAR C: CH128; J: INTEGER);
  609. EXTERNAL;
  610.  
  611. PROCEDURE WRITE1(C: CHAR);
  612. EXTERNAL;
  613.  
  614. PROCEDURE WRITEBLK;
  615. EXTERNAL;
  616.  
  617. PROCEDURE WRITEINT(INT: INTEGER);
  618.  
  619. VAR HOLD: CH20;
  620.     I,J: INTEGER;
  621. BEGIN
  622.    I := 0;
  623.    REPEAT
  624.       BEGIN
  625.      I := I+1;
  626.      HOLD[I] := CHR(ORD('0') + INT MOD 10);
  627.      INT := INT DIV 10;
  628.       END
  629.    UNTIL INT = 0;
  630.    FOR J := 0 TO I-1 DO
  631.       WRITE1(HOLD[I-J]);
  632. END;
  633.  
  634. PROCEDURE WRITEHEX(HEX: INTEGER);
  635.  
  636. VAR HOLD: CH20;
  637.     I,J: INTEGER;
  638. BEGIN
  639.    I := 0;
  640.    REPEAT
  641.       BEGIN
  642.      I := I+1;
  643.      HOLD[I] := ROEXTVAR.HEXCHAR[1 + SHIFT(SHIFT(HEX,12),-12)];
  644.      HEX := SHIFT(HEX,-4);
  645.       END;
  646.    UNTIL HEX = 0;
  647.    IF I = 1 THEN
  648.       WRITE1('0');
  649.    FOR J := 0 TO I-1 DO
  650.       WRITE1(HOLD[I-J]);
  651. END;
  652.  
  653. PROCEDURE WRITELAST; { write a <cr> }
  654. EXTERNAL;
  655.  
  656. PROCEDURE DISINT(INT: INTEGER);
  657. BEGIN
  658.    WRITEBLK;
  659.    WRITEINT(INT);
  660. END;
  661.  
  662. PROCEDURE DISHEX(HEX: INTEGER);
  663. BEGIN
  664.    WRITEBLK;
  665.    WRITE1('$');
  666.    WRITEHEX(HEX);
  667. END;
  668.  
  669. PROCEDURE DISCHR(CH: CHAR);
  670. BEGIN
  671.    DISHEX(ORD(CH));
  672. END;
  673.  
  674. PROCEDURE DISCALL(C: HEADCALL); { must not be VAR, part of kludge }
  675.  
  676. VAR I: 0..255;
  677. BEGIN
  678.    FOR I := 1 TO 6 DO
  679.       IF C.CALL[I] <> ' ' THEN
  680.      WRITE1(C.CALL[I]);
  681.    IF ORD(C.SSID) <> 0 THEN
  682.       BEGIN
  683.      WRITE1('-');
  684.      WRITEINT(ORD(C.SSID));
  685.       END;
  686. END;
  687.  
  688. PROCEDURE DISCLIST(CLIST: HEADTYPE; START: INTEGER; N: INTEGER);
  689. { write N calls in CLIST array starting at START }
  690.  
  691. VAR J: INTEGER;
  692. BEGIN
  693.    N := N + START - 1;
  694.    FOR J := START TO N DO
  695.       BEGIN
  696.      DISCALL(CLIST.CALLS[J]);
  697.      IF J <> N THEN
  698.         WRITE1(',');
  699.       END;
  700. END;
  701.  
  702. PROCEDURE HEXDUMP(VAR CH: FRCHTYPE; NBYTES: INTEGER; VAR TITLE: CH10);
  703.  
  704. VAR
  705.     JCHAR: CHAR;
  706.     I: INTEGER;
  707.     J: INTEGER;
  708.     SI: INTEGER;
  709.     LINE: INTEGER;
  710. BEGIN
  711.    WRITE10(TITLE,10);
  712.    WRITELAST;
  713.    I := 0;
  714.    WHILE NBYTES > 0 DO
  715.       BEGIN
  716.      IF NBYTES < 16 THEN
  717.         LINE := NBYTES
  718.      ELSE
  719.         LINE := 16;
  720.      SI := I;
  721.      WRITEHEX(I);
  722.      WRITE1('-');
  723.      FOR J := 1 TO LINE DO
  724.         BEGIN
  725.            WRITEHEX(ORD(CH[I]));
  726.            IF (I MOD 4) = 3 THEN
  727.           WRITEBLK;
  728.            I := I + 1;
  729.         END;
  730.      FOR J := 1 TO 4 + 2*((16-LINE) MOD 4) + 9*((16-LINE) DIV 4) DO
  731.         WRITEBLK;
  732.      IF ((16-LINE) MOD 4)<> 0 THEN
  733.         WRITEBLK;
  734.      I := SI;
  735.      FOR J := 1 TO LINE DO
  736.         BEGIN
  737.            JCHAR := CHR(ORD(CH[I]) DIV 2);
  738.            IF (JCHAR >= ' ') AND (JCHAR <= '~') THEN
  739.           WRITE1(JCHAR)
  740.            ELSE
  741.           WRITE1('.');
  742.            I := I+1;
  743.         END;
  744.      I := SI;
  745.      FOR J := 1 TO 3 + (16-LINE) DO
  746.         WRITEBLK;
  747.      FOR J := 1 TO LINE DO
  748.         BEGIN
  749.            JCHAR := CHR((ORD(CH[I])*2) DIV 2);
  750.            IF (JCHAR >= ' ') AND (JCHAR <= '~') THEN
  751.           WRITE1(JCHAR)
  752.            ELSE
  753.           WRITE1('.');
  754.            I := I + 1;
  755.         END;
  756.      WRITELAST;
  757.      NBYTES := NBYTES - LINE;
  758.       END;
  759. END;
  760.  
  761. PROCEDURE LAPBPROC(COMEV: FTYPE);
  762. { does the LAPB protocol using the procedures
  763.   MAKEHEAD, INTOS5, SHIPOUT, SHIPSUP, SHIPUI,
  764.   ACKFLIGHT, GETMYFRAME, CNCDSC, SENDFRMR }
  765.  
  766. VAR DATAORIG,NRCALC: INTEGER;
  767.     REVMID,REVHI,REV: 0..NUMHDCALL;
  768.  
  769. { The following variables are set if GETMYFRAME returns TRUE }
  770.     FRCLASS: EVTYPE;
  771.     VS,VR: INTEGER;
  772.     PFBIT: BOOLEAN;
  773.     NDATA,DOFFSET: INTEGER;
  774.  
  775.     LOCFRSIZE,LOCHDSIZE: INTEGER;
  776.     LOCFRAME: FRTYPE;
  777.     LOCHEAD: HEADTYPE;
  778.     WASMON: BOOLEAN;
  779.  
  780. PROCEDURE MAKEHEAD(REMCON: BOOLEAN; VAR INHEAD: HEADTYPE; N: INTEGER;
  781.            VAR OUTHEAD: HEADTYPE; VAR OUTHDSIZE: INTEGER);
  782. { INHEAD is the header structure, right justified.
  783.   OUTHEAD is the resulting structure, ready to send.
  784.   N is the number of calls, excluding MYCALL.
  785.   REMCON is true if the connect originates from another station.
  786.  
  787.  Construct OUTHEAD and OUTHDSIZE to place in front of all frames. }
  788.  
  789. VAR I,J,K: INTEGER;
  790. BEGIN
  791.    IF ACX.AX25 THEN
  792.       BEGIN { AX25 mode }
  793.     IF REMCON THEN
  794.        FOR I:=N DOWNTO 2 DO
  795.           OUTHEAD.CALLS[RPCALLX+I-2] := INHEAD.CALLS[RPCALLX+N-I]
  796.      ELSE
  797.        OUTHEAD := INHEAD;
  798.     OUTHEAD.CALLS[FRCALLX] := ACX.MYCALL;
  799.     IF N<=0 THEN
  800.        BEGIN
  801.           IF N=0 THEN
  802.          N := 1
  803.            ELSE
  804.          N := -N;
  805.           OUTHEAD.CALLS[TOCALLX].CALL := ROEXTVAR.BEACON;
  806.           OUTHEAD.CALLS[TOCALLX].SSID := CHR(0);
  807.        END
  808.      ELSE
  809.        OUTHEAD.CALLS[TOCALLX] := INHEAD.CALLS[FRCALLX];
  810.     OUTHDSIZE := NHEADSIZE*(N+1);
  811.     IF REMCON THEN
  812.        BEGIN { remote connection, must set up CNCCALL }
  813.           CNCCALL := OUTHEAD;
  814.           CNCCALL.CALLS[FRCALLX] := INHEAD.CALLS[FRCALLX];
  815.           CNCCNT := N;
  816.        END { remote connect stuff };
  817.     FOR I:=N+1 DOWNTO 1 DO
  818.        OUTHEAD.CALLS[I].SSID
  819.          := CHR((ORD(OUTHEAD.CALLS[I].SSID) MOD 16)+48);
  820.     FOR I:=0 TO OUTHDSIZE-1 DO
  821.        OUTHEAD.CH[I] := CHR(2*ORD(OUTHEAD.CH[I]));
  822.     OUTHEAD.CH[OUTHDSIZE-1] := SUCC(OUTHEAD.CH[OUTHDSIZE-1]);
  823.      END { AX25 mode }
  824.  
  825.    ELSE
  826.       BEGIN { Vancouver mode }
  827.      OUTHDSIZE := 1;
  828.      IF REMCON THEN { more remote connect stuff }
  829.         CNCCNT := 1;
  830.      IF ((ORD(INHEAD.VANCHEAD.VANID)> 128) AND REMCON) OR
  831.        (ACX.VRPT AND NOT REMCON) THEN
  832.         OUTHEAD.CH[0] := CHR(ORD(ACX.VANID)+128)
  833.       ELSE
  834.         OUTHEAD.CH[0] := ACX.VANID;
  835.       END { Vancouver mode }
  836. END { MAKEHEAD };
  837.  
  838. PROCEDURE INTOS5;
  839. { sets global variables up whenever I'm moving into S5, information transfer }
  840.  
  841. BEGIN { INTOS5 };
  842.    ACX.RETOUT := FALSE;
  843.    FLFIRST := 0;
  844.    FLCUR := 0;
  845.    FLNEXT := 0;
  846.    NR := 0;
  847.    SENDRNR := FALSE;
  848.    SENDFIN := FALSE;
  849.    RCVDRNR := FALSE;
  850.    RNRSIZE := 0;
  851.    SENDRR := FALSE;
  852.    SENDREJ := FALSE;
  853.    FLINFO[0].RP := ACX.AIRP;
  854.    ACX.T1.RUNNING := FALSE;
  855.    ACX.T1.PENDING := FALSE;
  856.    RETRYCNT := XRETRY;
  857.    IF LS<>LS5 THEN
  858.       BEGIN { issue connect message if not in transparent }
  859.      IF ACX.MODEF1 OR NMODEF2 OR ACX.MODEF2 THEN
  860.         BEGIN
  861.            WRITE20(ROEXTVAR.CONRQMSG,4);
  862.            WRITE15(ROEXTVAR.MSG.CONTO,13);
  863.            DISCALL(CONCALL);
  864.            WRITELAST;
  865.         END;
  866.      ACX.MODEF1 := FALSE;
  867.      ACX.MODEF2 := NMODEF2;
  868.      SETMOD; { tell LLR of mode change }
  869.       END;
  870.    LS := LS5;
  871.    RETRY_SIP := FALSE;
  872. END;
  873.  
  874. FUNCTION SHIPOUT: BOOLEAN;
  875. { Send out I frames.
  876.   Parameter FLCUR is FLFIRST if frames are to be retransmitted,
  877.         otherwise it is FLNEXT. }
  878.  
  879. VAR I,NEXTRP,NBYTES,NHEADC: INTEGER;
  880.     DONE: BOOLEAN;
  881. BEGIN { SHIPOUT }
  882.  
  883. { Assign new sequence numbers to I frames; that is, if new frames can
  884.   be generated, mark their starting position and count in terminal input ring.
  885.   If any I frames were sent out, return TRUE. }
  886.    DONE := FALSE;
  887.    SHIPOUT := FALSE;
  888.    REPEAT
  889.       DONE := ((FLNEXT-FLFIRST+MODULO) MOD 8) >= ACX.KMAX;
  890.       IF DONE = FALSE THEN
  891.      BEGIN
  892.         WRAPAI(FLINFO[FLNEXT].RP,NBYTES,NEXTRP);
  893.         IF NBYTES=0 THEN
  894.            DONE := TRUE
  895.         ELSE
  896.            BEGIN
  897.           FLINFO[FLNEXT].CNT := NBYTES;
  898.           FLNEXT := SUCC(ORD(FLNEXT)) MOD 8;
  899.           FLINFO[FLNEXT].RP := NEXTRP;
  900.            END;
  901.      END;
  902.    UNTIL DONE;
  903.  
  904. { Insert CONHEAD into local frame }
  905.    IF FLCUR<>FLNEXT THEN
  906.       FOR I:=0 TO CONHDSIZE-1 DO
  907.      LOCFRAME.CH[I] := CONHEAD.CH[I];
  908.  
  909.    NHEADC := CONHDSIZE + 1 + ORD(ACX.AX25 );
  910.    CALCFC; { insert something into ACX.HOFC }
  911. { Now send all I frames from FLCUR up to (but not including) FLNEXT }
  912.    WHILE (FLCUR<>FLNEXT) AND ((FLINFO[FLCUR].CNT+NHEADC) <= ACX.HOFC) DO
  913.       BEGIN
  914.      SHIPOUT := TRUE;
  915.      LOCFRAME.CH[NHEADC-1] := CHR(XPIDBYTE) { here is the magic PID byte!!! };
  916.      LOCFRAME.CH[CONHDSIZE] := CHR((NR*16+FLCUR)*2);
  917.      GETAI(FLINFO[FLCUR].RP,FLINFO[FLCUR].CNT,LOCFRAME.CH,NHEADC);
  918.      NBYTES := NHEADC+FLINFO[FLCUR].CNT;
  919.      IF DUMPOFRAME IN TRACEDATA.BITS THEN
  920.         BEGIN { show outgoing frame }
  921.            IF DUMPALLD IN TRACEDATA.BITS THEN
  922.           HEXDUMP(LOCFRAME.CH,NBYTES,ROEXTVAR.TITLEOUTFR)
  923.         ELSE
  924.           HEXDUMP(LOCFRAME.CH,NHEADC,ROEXTVAR.TITLEOUTFR);
  925.         END { trace stuff };
  926.      ACX.DIGOUT := FALSE;
  927.      PUTHO(LOCFRAME.CH,NBYTES);
  928.      CALCFC; { put something into ACX.HOFC }
  929.      FLCUR := SUCC(ORD(FLCUR)) MOD 8;
  930.      IF FLCUR=RETRY_SEQ THEN { last frame in retry sequence sent }
  931.         RETRY_SIP:=FALSE;
  932.      IF FALSE = (ACX.T1.RUNNING OR ACX.T1.PENDING OR RETRY_SIP) THEN
  933.         BEGIN
  934.            ACX.T1.PENDING := TRUE;
  935.            ACX.T1.TSTOP := ACX.IFTIME*ROEXTVAR.TICKSPS*CNCCNT;
  936.         END;
  937.       END;
  938.  
  939. END { SHIPOUT };
  940.  
  941. FUNCTION SHIPSUP(VAR HD: HEADTYPE; HDSIZE: INTEGER;
  942.          CNTRL: CHAR; NDAT: INTEGER): BOOLEAN;
  943. { If enough room exists in HDLC output ring, send out frame
  944.   with the control byte passed as a parameter and SHIPOUT TRUE }
  945.  
  946. VAR NBYTES,NHEADC,I: INTEGER;
  947. BEGIN { SHIPSUP }
  948.    NHEADC := HDSIZE + 1;
  949.    NBYTES := NHEADC + NDAT;
  950.    CALCFC; { calculate ACX.HOFC }
  951.    IF NBYTES < ACX.HOFC THEN
  952.       BEGIN
  953.      SHIPSUP := TRUE;
  954.      FOR I:=0 TO HDSIZE-1 DO
  955.         LOCFRAME.CH[I] := HD.CH[I];
  956.      LOCFRAME.CH[HDSIZE] := CNTRL;
  957.      IF DUMPOFRAME IN TRACEDATA.BITS THEN
  958.         BEGIN { show outgoing frame }
  959.            IF DUMPALLD IN TRACEDATA.BITS THEN
  960.           HEXDUMP(LOCFRAME.CH,NBYTES,ROEXTVAR.TITLEOUTFR)
  961.         ELSE
  962.           HEXDUMP(LOCFRAME.CH,NHEADC,ROEXTVAR.TITLEOUTFR);
  963.         END { trace stuff };
  964.      ACX.DIGOUT := FALSE;
  965.      PUTHO(LOCFRAME.CH,NBYTES);
  966.       END
  967.     ELSE
  968.       SHIPSUP := FALSE;
  969. END { SHIPSUP };
  970.  
  971. PROCEDURE SHIPUI(FROMAI: BOOLEAN);
  972. { Send out a UI frame from a beacon timeout, or disconnected input }
  973.  
  974. VAR NBYTES,NEWRP,NINFO,I: INTEGER;
  975. BEGIN { SHIPUI }
  976.    IF FROMAI THEN
  977.       BEGIN { get data from terminal ring }
  978.      IF ACX.UCONCNT=0 THEN
  979.         BEGIN
  980.            ACX.UCONCNT := 1;
  981.            UCONLST.CALLS[FRCALLX].CALL := ROEXTVAR.CQ;
  982.            UCONLST.CALLS[FRCALLX].SSID := CHR(0);
  983.         END;
  984.      MAKEHEAD(FALSE,UCONLST,ACX.UCONCNT,LOCHEAD,LOCHDSIZE);
  985.      WRAPAI(ACX.AIRP,NINFO,NEWRP);
  986.      NBYTES := LOCHDSIZE + 1 + ORD(ACX.AX25);
  987.      LOCFRAME.CH[LOCHDSIZE+1] := CHR(XPIDBYTE);
  988.      GETAI(ACX.AIRP,NINFO,LOCFRAME.CH,NBYTES);
  989.       END { data from terminal ring }
  990.     ELSE
  991.       BEGIN { data from beacon buffer }
  992.      MAKEHEAD(FALSE,UCONLST,-ACX.UCONCNT,LOCHEAD,LOCHDSIZE);
  993.      NINFO := ACX.BECLEN;
  994.      NBYTES := LOCHDSIZE + ORD(ACX.AX25);
  995.      LOCFRAME.CH[LOCHDSIZE+1] := CHR(XPIDBYTE);
  996.      FOR I:=1 TO ACX.BECLEN DO
  997.         LOCFRAME.CH[NBYTES+I] := ACY.BECTXT[I];
  998.       END;
  999.    IF SHIPSUP(LOCHEAD,LOCHDSIZE,CHR(03) {UI} ,NINFO+ORD(ACX.AX25)) THEN
  1000.       IF FROMAI THEN
  1001.      FLSHAI(NEWRP);
  1002. END { SHIPUI };
  1003.  
  1004. FUNCTION ACKFLIGHT(VR: INTEGER): BOOLEAN;
  1005. { Acknowledge all frames up to VR;
  1006.   return TRUE if VR parameter is valid,
  1007.      otherwise return FALSE }
  1008.  
  1009. VAR FRNO: INTEGER;
  1010.     NEMPTIED: INTEGER;
  1011. BEGIN
  1012.    FRNO := FLFIRST;
  1013.    NEMPTIED := 0;
  1014.    WHILE (FRNO<>FLNEXT) AND (VR<>FRNO) DO
  1015.       BEGIN
  1016.      NEMPTIED := NEMPTIED+FLINFO[FRNO].CNT;
  1017.      FRNO := SUCC(ORD(FRNO)) MOD 8;
  1018.       END;
  1019.    IF VR<>FRNO THEN
  1020.       ACKFLIGHT := FALSE
  1021.     ELSE
  1022.       BEGIN
  1023.      FLSHAI(FLINFO[VR].RP);
  1024.      ACKFLIGHT := TRUE;
  1025.      IF VR<>FLFIRST THEN
  1026.         BEGIN { at least one frame acknowledged }
  1027.         IF VR<>FLNEXT THEN
  1028.            BEGIN { there are still frames outstanding }
  1029.               ACX.T1.TSTOP := ACX.TICKER+ACX.IFTIME*ROEXTVAR.TICKSPS;
  1030.               ACX.T1.RUNNING := TRUE;
  1031.               ACX.T1.PENDING := FALSE;
  1032.               RETRYCNT := XRETRY;
  1033.               ACX.RETOUT := FALSE;
  1034.               RETRY_SIP := FALSE;
  1035.            END
  1036.          ELSE
  1037.            BEGIN { all frames ACKed }
  1038.               ACX.T1.RUNNING := FALSE;
  1039.               ACX.T1.PENDING := FALSE;
  1040.               ACX.RETOUT := FALSE;
  1041.               RETRY_SIP := FALSE;
  1042.            END;
  1043.         END;
  1044.      FLFIRST := VR;
  1045.       END;
  1046. END { ACKFLIGHT };
  1047.  
  1048. PROCEDURE DISPREQ;
  1049. { Show connect request message }
  1050.  
  1051. BEGIN {DISPREQ}
  1052.    IF ACX.MODEF1 OR ACX.MODEF2 THEN
  1053.       BEGIN
  1054.      WRITE20(ROEXTVAR.CONRQMSG,20);
  1055.      DISCALL(LOCHEAD.CALLS[FRCALLX]);
  1056.      WRITELAST;
  1057.       END;
  1058. END { DISPREQ };
  1059.  
  1060. FUNCTION GETMYFRAME: BOOLEAN;
  1061. { Primary function is to read frames and note which frames are useful.
  1062.   1. Checks for incoming frame present. If no frame present, return FALSE.
  1063.   2. Extract header of frame.
  1064.   3. If this frame is to be digipeated and if room exists, move to HDLC
  1065.      output buffer. Return FALSE for the funtion value.
  1066.   4. See if this frame is for me. If so, return TRUE for function value.
  1067.      A quick look at the control byte classifies the kind of record,
  1068.      and the header has been moved into LOCHEAD.
  1069.   5. Sets the global boolean 'WASMON' if this frame was monitored.
  1070. }
  1071.  
  1072. VAR HMAX,CBYTE,CBYTESP,I: INTEGER;
  1073.     RPTCALL,RPTBIT: INTEGER;
  1074.     FORME,DISPMON,MATCH,WASDIGI,IFDIGI,ISCONCALL: BOOLEAN;
  1075.  
  1076. FUNCTION CHKLIST(VAR L: MONLIST; C: HEADCALL): BOOLEAN;
  1077. { Checks for presence of callsign in a monitor list }
  1078.  
  1079. VAR I,J,K: 0..255;
  1080.     RESULT: BOOLEAN;
  1081. BEGIN { CHKLIST }
  1082.    RESULT := (L.CNT=0) AND L.ALL;
  1083.    FOR I := L.CNT DOWNTO 1 DO
  1084.       RESULT := RESULT OR (L.CALLS.CALLS[I].CALL=C.CALL);
  1085.    CHKLIST := RESULT;
  1086. END { CHKLIST };
  1087.  
  1088. PROCEDURE TESTCOM;
  1089. { Strips off the poll/final bit;
  1090.   checks for IFRAME,RR,RNR,REJ,UI type frames }
  1091.  
  1092. VAR X: 0..255;
  1093. BEGIN
  1094.    PFBIT := FALSE;
  1095.    IF (CBYTE MOD 32) >=16 THEN
  1096.       BEGIN
  1097.      CBYTESP := CBYTE - 16;
  1098.      PFBIT := TRUE
  1099.       END
  1100.     ELSE
  1101.       CBYTESP := CBYTE;
  1102.    X := CBYTE MOD 16;
  1103.    VS := (CBYTE DIV 2) MOD 8;
  1104.    VR := (CBYTE DIV 32);
  1105.    DOFFSET := LOCHDSIZE + 1 + ORD(ACX.AX25);
  1106.    NDATA := LOCFRSIZE - DOFFSET;
  1107.    IF ODD(CBYTE) = FALSE THEN
  1108.       FRCLASS := IFRAME
  1109.    ELSE IF CBYTESP = 3 THEN
  1110.       FRCLASS := UI
  1111.    ELSE IF X=1 THEN
  1112.       FRCLASS := RR
  1113.    ELSE IF X=5 THEN
  1114.       FRCLASS := RNR
  1115.    ELSE IF X=9 THEN
  1116.       FRCLASS := REJ;
  1117.    DISPMON := ((FRCLASS=UI) OR ((FRCLASS=IFRAME) AND ACX.MONALL)) AND ACX.MONON AND
  1118.           (ACX.MONCON OR (LS=LS1)) AND (ACX.MODEF2 OR ACX.MODEF1);
  1119.    IFDIGI :=((FRCLASS=UI) OR (FRCLASS=IFRAME))
  1120.           AND WASDIGI AND (MONDIGI IN TRACEDATA.BITS);
  1121. END { TESTCOM };
  1122.  
  1123. BEGIN { GETMYFRAME }
  1124.   WASMON := FALSE;
  1125.   WASDIGI := FALSE;
  1126.   GETMYFRAME := FALSE;
  1127.   FRCLASS := OTHERFR;
  1128.   IF ACX.HITSZ<>0 THEN
  1129.     BEGIN
  1130.       IF FALSE = ACX.BECEVY THEN
  1131.     BEGIN
  1132.       ACX.TBEACON.RUNNING := ACX.BECTIM<>0;
  1133.       ACX.TBEACON.TSTOP := ACX.TICKER + ROEXTVAR.TICKSPS*ACX.BECTIM*10;
  1134.     END;
  1135.       LOCFRSIZE := ACX.HITSZ;
  1136.  
  1137.       IF LOCFRSIZE>MAXFRAME THEN
  1138.     BEGIN { too big for me }
  1139.       LOCFRSIZE := MAXFRAME;
  1140.       GETHI(LOCFRAME.CH,LOCFRSIZE);
  1141.     END
  1142.        ELSE
  1143.     BEGIN { frame fits }
  1144.       DISPMON := FALSE;
  1145.       FORME := FALSE;
  1146.       GETHI(LOCFRAME.CH,LOCFRSIZE);
  1147.       IF DUMPFRAME IN TRACEDATA.BITS THEN BEGIN { show frame in hex }
  1148.         HEXDUMP(LOCFRAME.CH,LOCFRSIZE,ROEXTVAR.TITLERDFR); END;
  1149.       CALCFC; { calculate ACX.HOFC }
  1150.       CASE ACX.AX25 OF
  1151.         FALSE :
  1152.           BEGIN
  1153.         IF ACX.VANCDP AND (ORD(LOCFRAME.FRVAN.VANID)>128)
  1154.             AND (ORD(LOCFRAME.FRVAN.VANID)<160) THEN
  1155.           BEGIN { digipeat in Vancouver mode }
  1156.             IF LOCFRSIZE < ACX.HOFC THEN
  1157.               BEGIN
  1158.             ACX.DIGOUT := TRUE;
  1159.             LOCFRAME.FRVAN.VANID := CHR(32+ORD(LOCFRAME.FRVAN.VANID));
  1160.             PUTHO(LOCFRAME.CH,LOCFRSIZE);
  1161.             WASDIGI := TRUE;
  1162.               END;
  1163.           END;
  1164.         LOCHEAD.VANCHEAD := LOCFRAME.FRVAN;
  1165.         LOCHDSIZE := 1;
  1166.         CBYTE := ORD(LOCFRAME.FRVAN.VANCTL);
  1167.         FORME := (LOCFRSIZE=14) AND
  1168.             ((ORD(LOCFRAME.FRVAN.VANID)>=161) OR
  1169.             (ORD(LOCFRAME.FRVAN.VANID)<=127)) AND
  1170.             (LOCFRAME.FRVAN.TOCALL=ACX.MYCALL.CALL);
  1171.         FRCLASS := OTHERFR;
  1172.         MATCH := (ORD(LOCHEAD.VANCHEAD.VANID)=REMVANID)AND(LS<>LS1);
  1173.         TESTCOM;
  1174.         IF CBYTE=23 { connect request } THEN
  1175.           BEGIN
  1176.             FRCLASS := CONREQ;
  1177.             IF LS=LS1 THEN
  1178.               BEGIN
  1179.             NMODEF2 := ACX.CONMODE;
  1180.             MAKEHEAD(TRUE,LOCHEAD,0,CONHEAD,CONHDSIZE);
  1181.             CONCALL.CALL := LOCFRAME.FRVAN.FRCALL;
  1182.             CONCALL.SSID := CHR(0);
  1183.             GETMYFRAME := FORME;
  1184.             REMVANID := ORD(LOCFRAME.FRVAN.VANID);
  1185.               END
  1186.              ELSE
  1187.               GETMYFRAME := FORME AND (LOCFRAME.FRVAN.FRCALL=CONCALL.CALL);
  1188.           END
  1189.         ELSE IF CBYTE=7 { connect ACK } THEN
  1190.           BEGIN
  1191.             IF LOCFRAME.FRVAN.FRCALL=CONCALL.CALL THEN
  1192.               BEGIN
  1193.             FRCLASS := CONACK;
  1194.             GETMYFRAME:=FORME;
  1195.             REMVANID := ORD(LOCFRAME.FRVAN.VANID);
  1196.               END
  1197.           END
  1198.         ELSE IF CBYTE=83 { disconnect req } THEN
  1199.           BEGIN
  1200.             FRCLASS := DISREQ;
  1201.             GETMYFRAME := MATCH;
  1202.           END
  1203.         ELSE IF CBYTE=67{ disconnect ACK } THEN
  1204.           BEGIN
  1205.             FRCLASS := DISACK;
  1206.             GETMYFRAME := MATCH;
  1207.           END
  1208.         ELSE
  1209.           GETMYFRAME:=MATCH;
  1210.           IF DISPMON OR IFDIGI THEN
  1211.             BEGIN { monitor mode stuff }
  1212.               DISINT(ORD(LOCFRAME.CH[0]));
  1213.               WRITE1(':');
  1214.               PUTAO(LOCFRAME.CH,DOFFSET,NDATA);
  1215.               WRITELAST;
  1216.               WASMON := TRUE;
  1217.             END { monitor mode stuff };
  1218.           END { nondigipeat Vancouver };
  1219.         TRUE :
  1220.           BEGIN { AX25 mode }
  1221.         RPTBIT := 0;
  1222.         LOCHDSIZE := 0;
  1223.         HMAX := NUMHDCALL*NHEADSIZE;
  1224.         REPEAT
  1225.           LOCHEAD.CH[LOCHDSIZE] := CHR(ORD(LOCFRAME.CH[LOCHDSIZE])DIV 2);
  1226.           LOCHDSIZE := SUCC(LOCHDSIZE);
  1227.         UNTIL ODD(ORD(LOCFRAME.CH[LOCHDSIZE-1]))
  1228.             OR (LOCHDSIZE>HMAX);
  1229.         LASTCALL := LOCHDSIZE DIV NHEADSIZE;
  1230.         FOR I:=1 TO LASTCALL DO
  1231.           WITH LOCHEAD.CALLS[I] DO
  1232.             BEGIN
  1233.               IF ORD(SSID)>64 THEN
  1234.             RPTBIT := I;
  1235.               SSID := CHR(ORD(SSID) MOD 16);
  1236.             END;
  1237.         IF LASTCALL>2 THEN BEGIN
  1238.           IF RPTBIT=0 THEN
  1239.             RPTBIT := 3
  1240.            ELSE
  1241.             RPTBIT := RPTBIT + 1; END
  1242.          ELSE
  1243.           RPTBIT := 3;
  1244.         RPTCALL := RPTBIT;
  1245.         IF ((LOCHDSIZE MOD NHEADSIZE)=0 )
  1246.             AND (LASTCALL>1) AND (LOCFRSIZE>LOCHDSIZE) THEN
  1247.           BEGIN
  1248.             IF (RPTCALL<=LASTCALL) AND
  1249.             (LOCHEAD.CALLS[RPTCALL].SSID=ACX.MYCALL.SSID) AND
  1250.             (LOCHEAD.CALLS[RPTCALL].CALL=ACX.MYCALL.CALL) THEN
  1251.               BEGIN { frame to digipeat }
  1252.             LOCFRAME.CALLS[RPTBIT].SSID := CHR(ORD(LOCFRAME.CALLS[RPTBIT].SSID)+128);
  1253.             ACX.DIGOUT := TRUE;
  1254.             IF (LOCFRSIZE < ACX.HOFC) AND ACX.RPTOK THEN
  1255.               PUTHO(LOCFRAME.CH,LOCFRSIZE);
  1256.             WASDIGI := TRUE;
  1257.               END;
  1258.             WITH LOCHEAD.CALLS[TOCALLX] DO
  1259.               FORME := (CALL=ACX.MYCALL.CALL) AND
  1260.               (SSID=ACX.MYCALL.SSID) AND
  1261.               (RPTCALL>LASTCALL);
  1262.             CBYTE := ORD(LOCFRAME.CH[LOCHDSIZE]);
  1263.             TESTCOM;
  1264.             IF FRCLASS=OTHERFR THEN
  1265.               BEGIN { not IFRAME,RR,RNR,REJ,UI }
  1266.             IF CBYTESP=47 THEN
  1267.               BEGIN
  1268.                 FRCLASS := SABM;
  1269.                 IF LS=LS1 THEN
  1270.                   BEGIN
  1271.                 NMODEF2 := ACX.CONMODE;
  1272.                 MAKEHEAD(TRUE,LOCHEAD,LASTCALL-1,CONHEAD,CONHDSIZE);
  1273.                 CONCALL := LOCHEAD.CALLS[FRCALLX];
  1274.                 CONCALL.SSID := CHR(ORD(CONCALL.SSID) MOD 16);
  1275.                   END;
  1276.               END
  1277.             ELSE IF CBYTESP=67 THEN
  1278.               FRCLASS := DISC
  1279.             ELSE IF CBYTESP=15 THEN
  1280.               FRCLASS := DM
  1281.             ELSE IF CBYTESP=99 THEN
  1282.               FRCLASS := UA
  1283.             ELSE IF CBYTESP=135 THEN
  1284.               FRCLASS := FRMR;
  1285.               END;
  1286.             IF LS<>LS1 {IDLE} THEN
  1287.               WITH LOCHEAD.CALLS[FRCALLX] DO
  1288.             ISCONCALL := (CALL=CONCALL.CALL) AND
  1289.                 (SSID=CONCALL.SSID) AND FORME
  1290.              ELSE
  1291.               ISCONCALL := FORME;
  1292.               GETMYFRAME := ISCONCALL;
  1293.           END { proper AX25 frame };
  1294.         IF IFDIGI OR (DISPMON AND
  1295.             ( CHKLIST(MON.FRLIST,LOCHEAD.CALLS[FRCALLX]) OR
  1296.             CHKLIST(MON.TOLIST,LOCHEAD.CALLS[TOCALLX]))) THEN
  1297.           BEGIN { monitor mode stuff }
  1298.             DISCALL(LOCHEAD.CALLS[FRCALLX]);
  1299.             WRITE1('>');
  1300.             DISCALL(LOCHEAD.CALLS[TOCALLX]);
  1301.             WRITE1(':');
  1302.             PUTAO(LOCFRAME.CH,DOFFSET,NDATA);
  1303.             WRITELAST;
  1304.             WASMON := TRUE;
  1305.           END { monitor mode stuff };
  1306.           END { AX25 protocol };
  1307.         END { CASE };
  1308.     END { frame fits };
  1309.     END { input frame exists };
  1310.   IF WASDIGI AND (DUMPDIGI IN TRACEDATA.BITS) AND (NOT WASMON) THEN
  1311.     HEXDUMP(LOCFRAME.CH,LOCFRSIZE,ROEXTVAR.TITLEOUTFR);
  1312.  
  1313.   IF FORME AND (FRCLASS=SABM) AND
  1314.       (((LS=LS1) AND NOT ACX.CONOK) OR
  1315.       ((LS<>LS1) AND FORME AND NOT ISCONCALL)) THEN
  1316.     BEGIN { SABM coming out of the blue from someone else
  1317.        besides the station I'm connected to OR CONOK reset }
  1318.       MAKEHEAD(TRUE,LOCHEAD,LASTCALL-1,LOCFRAME.DMRHEAD,I);
  1319.       MATCH := SHIPSUP(LOCFRAME.DMRHEAD,I,CHR(15){DM},0);
  1320.       DISPREQ; { show call of station trying to connect }
  1321.     END;
  1322. END { GETMYFRAME };
  1323.  
  1324. PROCEDURE CNCDSC(EV:EVTYPE);
  1325. { An event has happened that could affect connect/disconnedt status }
  1326.  
  1327. VAR DONE: BOOLEAN;
  1328.     OLDLS,NEWLS: LSTYPE;
  1329.     CUREV: EVTYPE;
  1330.     CURACT: CNCACT;
  1331.     I,NBYTES: INTEGER;
  1332.  
  1333. PROCEDURE VANC_CON(C: CHAR; DORETRY: BOOLEAN);
  1334. { Procedure to send & receive Vancouver connect/disconnect frames }
  1335.  
  1336. VAR NBYTES: INTEGER;
  1337. BEGIN
  1338.    NBYTES := 14;
  1339.    LOCFRAME.FRVAN.FRCALL := ACX.MYCALL.CALL;
  1340.    LOCFRAME.FRVAN.TOCALL := CONCALL.CALL;
  1341.    LOCFRAME.FRVAN.VANCTL := C;
  1342.    LOCFRAME.FRVAN.VANID := CONHEAD.VANCHEAD.VANID;
  1343.    CALCFC; { calcualte ACX.HOFC }
  1344.    IF NBYTES<=ACX.HOFC THEN
  1345.       BEGIN
  1346.      IF DUMPOFRAME IN TRACEDATA.BITS THEN
  1347.         BEGIN { show outgoing frame }
  1348.            HEXDUMP(LOCFRAME.CH,NBYTES,ROEXTVAR.TITLEOUTFR);
  1349.         END { trace stuff };
  1350.      PUTHO(LOCFRAME.CH,NBYTES);
  1351.       END
  1352.     ELSE
  1353.       RETRYCNT := RETRYCNT+ORD(DORETRY AND (RETRYCNT>0));
  1354. END;
  1355.  
  1356. PROCEDURE AX25_CON(C: CHAR; DORETRY: BOOLEAN);
  1357. { Procedure to send AX25 connect/disconnect frames }
  1358.  
  1359. BEGIN { AX25_CON }
  1360.    IF FALSE = SHIPSUP(CONHEAD,CONHDSIZE,C,0) THEN
  1361.       { Note: RETRYCNT has been decremented by caller }
  1362.       RETRYCNT := RETRYCNT+ORD(DORETRY AND (RETRYCNT>0));
  1363. END { AX25_CON };
  1364.  
  1365. BEGIN { CNCDSC }
  1366.    IF FALSE = (ACX.T1.RUNNING OR ACX.T1.PENDING) THEN
  1367.       BEGIN
  1368.      ACX.T1.RUNNING := FALSE;
  1369.      ACX.T1.PENDING := TRUE;
  1370.      ACX.T1.TSTOP := ACX.IFTIME*ROEXTVAR.TICKSPS*CNCCNT;
  1371.       END;
  1372.    REPEAT
  1373.       OFRMRBUF[8] := CHR(ORD(EV));
  1374.       DONE := TRUE;
  1375.       OLDLS := LS; { record for possible trace }
  1376.       CUREV := EV;
  1377.       CURACT := ROEXTVAR.CNCACTION[LS,EV,ACX.AX25];
  1378.       CASE CURACT OF
  1379.      NOP_CNC: ;
  1380.      UA_S5_CNC:
  1381.         IF (LS<>LS1) OR ACX.CONOK THEN
  1382.            BEGIN { event: SABM, state: LS1,LS3,LS5 }
  1383.           MAKEHEAD(TRUE,LOCHEAD,LASTCALL-1,CONHEAD,CONHDSIZE);
  1384.           AX25_CON(CHR(99) {UA} ,FALSE);
  1385.           INTOS5;
  1386.            END;
  1387.      DM_CNC:
  1388.         BEGIN { event: SABM, state: LS4; event: DISC, state: LS1 }
  1389.            AX25_CON(CHR(15) {DM} ,TRUE); { may report N2EXCEED }
  1390.         END;
  1391.      DISC_CNC:
  1392.         BEGIN { event: T1RO, state: LS4 }
  1393.            AX25_CON(CHR(67) {DISC} ,TRUE);
  1394.         END;
  1395.      UA_CNC:
  1396.         BEGIN { event: SABM, state: LS2; event: DISC, state: LS4 }
  1397.            AX25_CON(CHR(99) {UA} ,FALSE);
  1398.         END;
  1399.      DM_S1_CNC:
  1400.         BEGIN { event: DISC, state: LS2 }
  1401.            AX25_CON(CHR(15) {DM} ,FALSE);
  1402.            RETRYCNT := XRETRY;
  1403.            LS := LS1;
  1404.         END;
  1405.      UA_S1_CNC:
  1406.         BEGIN { event: FRMR, state: LS2,LS3,LS5; event: DISC, state: LS5 }
  1407.            IF (DUMPFRMR IN TRACEDATA.BITS) AND (EV=FRMR) THEN
  1408.           HEXDUMP(LOCFRAME.CH,LOCFRSIZE,ROEXTVAR.FRMRRCVD);
  1409.            AX25_CON(CHR(99) {UA} ,FALSE);
  1410.            RETRYCNT := XRETRY;
  1411.            LS := LS1;
  1412.         END;
  1413.      M_S5_CNC:
  1414.         INTOS5; { event: UA, state: LS2 }
  1415.      BAILOUT_CNC:
  1416.         BEGIN { event: N2EXCEED, state: LS2,LS3,LS4,LS5 OR }
  1417.            RETRYCNT := XRETRY;
  1418.            LS := LS1;
  1419.            IF NMODEF2 OR ACX.MODEF1 OR ACX.MODEF2 THEN
  1420.           BEGIN
  1421.              WRITE20(ROEXTVAR.RETRYZERO,20);
  1422.              WRITELAST;
  1423.           END;
  1424.         END;
  1425.      M_S1_CNC:
  1426.         BEGIN { event: UA, state: LS4 (AX25);
  1427.             event: DM, state: LS4
  1428.             event: DISACK, state: LS4 (AX25) }
  1429.            RETRYCNT := XRETRY;
  1430.            LS := LS1;
  1431.         END;
  1432.      SABM_CNC:
  1433.         BEGIN { event: T1RO, state: LS2 }
  1434.            AX25_CON(CHR(47) {SABM} ,TRUE); { may report event N2EXCEED }
  1435.         END;
  1436.      SABM_S2_CNC:
  1437.         IF (LS<>LS1) OR ACX.CONOK THEN
  1438.            BEGIN { event: DM,FRMR, state: LS3,LS5;
  1439.                event: T1RO, state: LS1;
  1440.                event: UA, state: LS5 }
  1441.                 AX25_CON(CHR(47){SABM},FALSE);
  1442.           RETRYCNT := XRETRY;
  1443.           LS := LS2;
  1444.            END;
  1445.      FRMR_CNC:
  1446.         BEGIN { event: T1RO, state: LS3 }
  1447.            FOR I:=1 TO 8 DO
  1448.           LOCFRAME.CH[CONHDSIZE+I] := OFRMRBUF[I];
  1449.            IF SHIPSUP(CONHEAD,CONHDSIZE,CHR(135){FRMR},8) THEN
  1450.           RETRYCNT := RETRYCNT-ORD(RETRYCNT>0);
  1451.         END;
  1452.      CONR_CNC:
  1453.         BEGIN { event: T1RO, state: LS1,LS2 }
  1454.            VANC_CON(CHR(23) {CON REQ} ,TRUE);
  1455.            LS := LS2; { may report event N2EXCEED }
  1456.         END;
  1457.      CONA_CNC:
  1458.         IF (LS<>LS1) OR ACX.CONOK THEN
  1459.            BEGIN { event: CONREQ, state: LS1,LS2,LS5 }
  1460.           REMVANID := ORD(LOCFRAME.FRVAN.VANID);
  1461.           VANC_CON(CHR(7){CON ACK},FALSE);
  1462.           INTOS5;
  1463.            END
  1464.         ELSE IF LS=LS1 THEN
  1465.            BEGIN { show request for caller }
  1466.           LOCHEAD.CALLS[FRCALLX].CALL := LOCFRAME.FRVAN.FRCALL;
  1467.           LOCHEAD.CALLS[TOCALLX].SSID := CHR(0);
  1468.           DISPREQ;
  1469.            END;
  1470.      DISR_CNC:
  1471.         BEGIN { event: T1RO, state: LS4 }
  1472.            VANC_CON(CHR(83) {DIS REQ} ,TRUE); { may report event N2EXCEED }
  1473.         END;
  1474.      DISA_CNC:
  1475.         BEGIN { event: DISREQ, state: LS2,LS4,LS5 }
  1476.            VANC_CON(CHR(67) {DIS ACK} ,FALSE);
  1477.            RETRYCNT := XRETRY;
  1478.            LS := LS1;
  1479.         END;
  1480.      SAYBUSY_CNC:
  1481.         BEGIN { event: DM, state: LS2 }
  1482.            LS := LS1;
  1483.            WRITE20(ROEXTVAR.CONRQMSG,4); {*** }
  1484.            DISCALL(CONCALL);   { call sign }
  1485.            WRITE5(ROEXTVAR.BUSYMSG,5); { busy }
  1486.            WRITELAST;
  1487.         END;
  1488.       END { CASE };
  1489.       IF DUMPSTATE IN TRACEDATA.BITS THEN
  1490.      BEGIN { show old state, event, action, new state }
  1491.         WRITE10(ROEXTVAR.STATEMOD,10);
  1492.         DISINT(ORD(OLDLS));
  1493.         DISINT(ORD(CUREV));
  1494.         DISINT(ORD(CURACT));
  1495.         DISINT(ORD(LS));
  1496.         WRITELAST;
  1497.      END { trace code };
  1498.       IF (LS=LS1) AND (OLDLS<>LS1) THEN
  1499.      BEGIN
  1500.         IF (ACX.MODEF1 OR ACX.MODEF2) THEN
  1501.            BEGIN
  1502.           WRITE20(ROEXTVAR.CONRQMSG,4);
  1503.           WRITE15(ROEXTVAR.MSG.DISCON,12);
  1504.           WRITELAST;
  1505.           IF ACX.MODEF1 THEN
  1506.              BEGIN
  1507.             WRITE5(ROEXTVAR.MSG.PROMPT,4);
  1508.              END
  1509.            END;
  1510.         ACX.RETOUT:=FALSE;
  1511.         IF ACX.CWID AND ((OLDLS=LS4) OR (OLDLS=LS5)) THEN
  1512.            CWID;
  1513.      END;
  1514.    UNTIL DONE;
  1515.    I := ORD(LS);
  1516.    LLRINF(I);
  1517. END { CNCDSC };
  1518.  
  1519. PROCEDURE SENDFRMR(WXYZ:CHAR;CODENUM:CHAR);
  1520.  
  1521. BEGIN { SENDFRMR }
  1522.    OFRMRBUF[1] := LOCFRAME.CH[LOCHDSIZE];
  1523.    OFRMRBUF[2] := CHR((NR*16+FLNEXT)*2);
  1524.    OFRMRBUF[3] := WXYZ;
  1525.    OFRMRBUF[4] := CODENUM;
  1526.    OFRMRBUF[5] := CHR(ORD(LS));
  1527.    OFRMRBUF[6] := CHR(FLFIRST);
  1528.    OFRMRBUF[7] := CHR(FLCUR);
  1529.    ACX.T1.RUNNING := FALSE;
  1530.    ACX.T1.PENDING := FALSE;
  1531.    RETRYCNT := XRETRY;
  1532.    IF ACX.AX25 THEN
  1533.       BEGIN { tell other side }
  1534.      LS := LS3;
  1535.      CNCDSC(T1RO);
  1536.      IF DUMPFRMR IN TRACEDATA.BITS THEN
  1537.         HEXDUMP(LOCFRAME.CH,CONHDSIZE+9,ROEXTVAR.FRMRSENT);
  1538.       END
  1539.    ELSE
  1540.       BEGIN { don't tell other side, but disconnect }
  1541.      LS := LS4;
  1542.      CNCDSC(T1RO);
  1543.       END;
  1544. END { SENDFRMR };
  1545.  
  1546. BEGIN { LAPBPROC }
  1547.    WHILE GETMYFRAME DO
  1548.       BEGIN { frame for me }
  1549.      IF DUMPIFRAME IN TRACEDATA.BITS THEN
  1550.         BEGIN { dump incoming frame, I'm going to use it }
  1551.            HEXDUMP(LOCFRAME.CH,LOCFRSIZE,ROEXTVAR.TITLEUSFR);
  1552.         END { dumping incoming frame };
  1553.      IF (FRCLASS>=SABM) THEN
  1554.         BEGIN
  1555.            IF FRCLASS<DISREQ THEN
  1556.           CNCDSC(FRCLASS)
  1557.            ELSE
  1558.           CNCDSC(ROEXTVAR.VANCMAP[FRCLASS])
  1559.         END
  1560.      ELSE IF (FRCLASS=OTHERFR) AND (LS>LS1) THEN
  1561.         SENDFRMR(CHR(1),CHR(1))
  1562.      ELSE IF LS=LS5 THEN
  1563.         CASE FRCLASS OF
  1564.            OTHERFR,T1RO,N2EXCEED: ; { impossible to get here }
  1565.            RR:
  1566.           IF ACKFLIGHT(VR) THEN
  1567.              RCVDRNR := FALSE
  1568.            ELSE
  1569.              SENDFRMR(CHR(8),CHR(2));
  1570.            REJ:
  1571.           IF ACKFLIGHT(VR) THEN
  1572.              BEGIN { valid REJ code }
  1573.             IF ACX. FULLDUP THEN
  1574.                BEGIN { full duplex code }
  1575.                  { For the time being, tread REJ like RR when
  1576.                    in full duplex mode.  This should get changed
  1577.                    when link level code is added, to abort all
  1578.                    queued up HDLC output. }
  1579.                 { FLCUR := FLFIRST;
  1580.                   HDLCABORT; }
  1581.                END
  1582.              ELSE
  1583.                BEGIN { half duplex mode }
  1584.                   FLCUR := FLFIRST
  1585.                END { half duplex mode }
  1586.              END { valid REJ code }
  1587.            ELSE
  1588.              SENDFRMR(CHR(8),CHR(3));
  1589.            RNR:
  1590.           IF ACKFLIGHT(VR) THEN
  1591.              BEGIN { start up timer immediately }
  1592.             RCVDRNR := TRUE;
  1593.             ACX.T1.TSTOP := ACX.TICKER+2*ACX.IFTIME*ROEXTVAR.TICKSPS;
  1594.             ACX.T1.RUNNING := TRUE;
  1595.             ACX.T1.PENDING := FALSE;
  1596.             RETRYCNT:=XRETRY;
  1597.              END
  1598.            ELSE
  1599.              SENDFRMR(CHR(8),CHR(4));
  1600.            IFRAME:
  1601.           BEGIN
  1602.              SENDFIN:=(FALSE=(DONTFINL IN TRACEDATA.BITS))
  1603.                  AND PFBIT AND ACX.AX25;
  1604.              IF VS=NR THEN
  1605.             BEGIN
  1606.                CALCFC; { calculate ACX.AOFC }
  1607.                IF NDATA<=ACX.AOFC THEN
  1608.                   BEGIN
  1609.                  IF WASMON=FALSE THEN { dont show info twice if monitored }
  1610.                     PUTAO(LOCFRAME.CH,DOFFSET,NDATA);
  1611.                  NR := SUCC(ORD(NR)) MOD 8;
  1612.                  SENDRR := TRUE;
  1613.                  ACX.DCDDRP := FALSE;
  1614.                   END
  1615.                 ELSE
  1616.                   BEGIN
  1617.                  SENDRNR := TRUE;
  1618.                  ACX.DCDDRP := FALSE;
  1619.                   END
  1620.             END
  1621.               ELSE
  1622.             BEGIN
  1623.                SENDREJ := ACX.AX25;
  1624.                SENDRR := TRUE;
  1625.                ACX.DCDDRP := FALSE;
  1626.                RNRSIZE := NDATA;
  1627.             END;
  1628.              IF FALSE = ACKFLIGHT(VR) THEN
  1629.             SENDFRMR(CHR(8),CHR(5));
  1630.           END;
  1631.         END { CASE };
  1632.       END { frame for me };
  1633.  
  1634.    IF ACX.T1.RUNNING THEN
  1635.       BEGIN
  1636.      TICKTEMP := ACX.TICKER-ACX.T1.TSTOP; { will overflow }
  1637.      IF TICKTEMP>0 THEN
  1638.         BEGIN
  1639.            ACX.T1.RUNNING := FALSE;
  1640.            ACX.T1.PENDING := FALSE;
  1641.            ACX.RETOUT := LS<>LS1;
  1642.            IF LS<>LS1 THEN
  1643.           BEGIN
  1644.              IF RETRYCNT=0 THEN
  1645.             CNCDSC(N2EXCEED)
  1646.               ELSE
  1647.             BEGIN
  1648.                IF LS<>LS5 THEN
  1649.                BEGIN
  1650.                   RETRYCNT := RETRYCNT-ORD(RETRYCNT>0);
  1651.                   CNCDSC(T1RO);
  1652.                   END
  1653.                 ELSE
  1654.                 IF FALSE=RETRY_SIP THEN
  1655.                   BEGIN { resend all I frames outstanding, forget RNR received }
  1656.                  RCVDRNR := FALSE;
  1657.                  FLCUR := FLFIRST;
  1658.                  RETRY_SIP := FLCUR<>FLNEXT;
  1659.                  RETRY_SEQ:=FLNEXT {RETRY FINISH POINT};
  1660.                  RETRYCNT := RETRYCNT-ORD(RETRYCNT>0);
  1661.                   END
  1662.             END
  1663.           END;
  1664.         END;
  1665.       END;
  1666.  
  1667.    IF ACX.TBEACON.RUNNING THEN
  1668.       BEGIN
  1669.      TICKTEMP := ACX.TICKER-ACX.TBEACON.TSTOP; { will overflow }
  1670.      IF TICKTEMP>0 THEN
  1671.         BEGIN { time to do beacon }
  1672.            ACX.TBEACON.RUNNING := (ACX.BECTIM<>0) AND ACX.BECEVY;
  1673.            ACX.TBEACON.TSTOP := ACX.TICKER+ROEXTVAR.TICKSPS*ACX.BECTIM*10;
  1674.            SHIPUI(FALSE);
  1675.         END;
  1676.       END { beacon stuff };
  1677.    IF LS=LS1 THEN
  1678.       BEGIN { test for data input; it becomes UI frame }
  1679.      WRAPAI(ACX.AIRP,LOCFRSIZE,LOCHDSIZE);
  1680.      IF LOCFRSIZE<>0 THEN
  1681.         SHIPUI(TRUE);
  1682.       END { test for data becoming UI frames };
  1683.    IF LS=LS5 THEN
  1684.       BEGIN
  1685.      IF (NOT ACX.DCD) OR ACX.DCDDRP OR ACX.FULLDUP THEN
  1686.         BEGIN
  1687.            NRCALC:=(NR*2+ORD(SENDFIN))*16;
  1688.            IF RNRSIZE<>0 THEN
  1689.           BEGIN
  1690.              CALCFC;
  1691.              SENDRR := ACX.AOFC>=RNRSIZE;
  1692.           END;
  1693.            IF SENDRNR THEN
  1694.           BEGIN
  1695.              IF SHIPSUP(CONHEAD,CONHDSIZE,CHR(NRCALC+5 {RNR} ),0) THEN
  1696.             BEGIN
  1697.                SENDRNR := FALSE;
  1698.                SENDREJ := FALSE;
  1699.                SENDRR := FALSE; SENDFIN:=FALSE;
  1700.             END
  1701.           END
  1702.            ELSE IF SENDREJ THEN
  1703.           BEGIN
  1704.              IF SHIPSUP(CONHEAD,CONHDSIZE,CHR(NRCALC+9 {REJ} ),0) THEN
  1705.             BEGIN
  1706.                SENDREJ := FALSE;
  1707.                SENDRR := FALSE; SENDFIN:=FALSE;
  1708.             END
  1709.           END;
  1710.            IF FALSE = (RCVDRNR OR SENDFIN) THEN
  1711.           BEGIN
  1712.              IF SHIPOUT THEN
  1713.             SENDRR := FALSE;
  1714.           END;
  1715.            IF SENDRR OR SENDFIN THEN
  1716.           IF SHIPSUP(CONHEAD,CONHDSIZE,CHR(NRCALC+1{RR}),0) THEN
  1717.              BEGIN
  1718.             RNRSIZE:=0;
  1719.             SENDRR := FALSE ;  SENDFIN:=FALSE;
  1720.              END;
  1721.         END { DCD drop sturr };
  1722.       END { LS=LS5 };
  1723.    CASE COMEV OF
  1724.       F_NULL: ;
  1725.       F_CON: { connect command }
  1726.      IF LS=LS1 THEN
  1727.         BEGIN { start everything with T1RO }
  1728.            MAKEHEAD(FALSE,CNCCALL,CNCCNT,CONHEAD,CONHDSIZE);
  1729.            CONCALL := CNCCALL.CALLS[FRCALLX];
  1730.            ACX.T1.RUNNING := FALSE;
  1731.            ACX.T1.PENDING := FALSE;
  1732.            LS := LS2; { kludge to avoid CONOK test }
  1733.            RETRYCNT := XRETRY;
  1734.            CNCDSC(T1RO);
  1735.         END;
  1736.       F_DISC:
  1737.      BEGIN { disconnect command }
  1738.         IF LS=LS5 THEN
  1739.            BEGIN
  1740.           LS := LS4;
  1741.           RETRYCNT := XRETRY;
  1742.           CNCDSC(T1RO);
  1743.            END
  1744.          ELSE
  1745.            CNCDSC(N2EXCEED);
  1746.      END;
  1747.    END { CASE };
  1748.  
  1749. { Finally, check to see if no HDLC output is in progress
  1750.   and timer T1 has its pending bit set.
  1751.   If these conditions are satisfied, then start timer T1 }
  1752.  
  1753.    IF (FALSE = ACX.T1.RUNNING) AND ACX.T1.PENDING AND (FALSE = ACX.HACT) THEN
  1754.       BEGIN { the time has come to start the timer, T1.TSTOP has interval }
  1755.      ACX.T1.RUNNING:=TRUE;
  1756.      ACX.T1.PENDING:=FALSE;
  1757.      ACX.T1.TSTOP := ACX.TICKER+ACX.T1.TSTOP;
  1758.       END;
  1759. END { LAPBPROC };
  1760.  
  1761. FUNCTION COMPARSE: FTYPE;
  1762.  
  1763. VAR
  1764.  
  1765.     BUF: BUFTYPE;
  1766.     ARS: INTEGER;
  1767.     POINT: 1..BUFRSIZE { pointer into buffer };
  1768.     PPOINT: INTEGER;
  1769.     PNUM,I,TC: INTEGER;
  1770.     TYPTOKEN: (NOTOKEN,ALFTOKEN,NUMTOKEN,HEXTOKEN,ERRTOKEN);
  1771.     TOKEN: CH8;
  1772.     CTYPE: COM_TYPE;
  1773.     LTYPE: LIT_TYPE;
  1774.     LOOKING,MATCH,GOODVAL: BOOLEAN;
  1775.     OK: BOOLEAN;
  1776.     EH: BOOLEAN;
  1777.     TBIT: BOOLEAN;
  1778.     KLUDGE: HEADCALL;
  1779.     W8FIX: CH8; { kludge to avoid compiler problem }
  1780.     CMPRS: FTYPE;
  1781.  
  1782. FUNCTION SP_SKIP(I: INTEGER): BOOLEAN;
  1783.  
  1784. VAR LOOPING: BOOLEAN;
  1785. BEGIN { SP_SKIP }
  1786.    LOOPING := TRUE;
  1787.    POINT := I;
  1788.    WHILE LOOPING DO
  1789.       BEGIN
  1790.      IF POINT >ARS THEN
  1791.         LOOPING := FALSE
  1792.      ELSE IF BUF[POINT]=' ' THEN
  1793.         POINT := POINT+1
  1794.       ELSE
  1795.         LOOPING := FALSE;
  1796.       END { do while looping };
  1797.    SP_SKIP := POINT<=ARS;
  1798. END { SP_SKIP };
  1799.  
  1800. FUNCTION UPPER(C: CHAR): CHAR;
  1801.  
  1802. BEGIN
  1803.    IF (C >= 'a') AND (C <= 'z') THEN
  1804.       UPPER := CHR(ORD(C)-ORD('a')+ORD('A'))
  1805.     ELSE
  1806.       UPPER := C;
  1807. END;
  1808.  
  1809. PROCEDURE PTOKEN(NPOINT:INTEGER);
  1810.  
  1811. VAR I: 0..255;
  1812.     C: CHAR;
  1813.     LOOPING: BOOLEAN;
  1814. BEGIN { TOKEN }
  1815.    FOR I := 1 TO 8 DO
  1816.       TOKEN[I] := ' ';
  1817.    LOOPING := SP_SKIP(NPOINT);
  1818.    PPOINT := POINT;
  1819.    PNUM := 0;
  1820.    TC := 0;
  1821.    TYPTOKEN := NOTOKEN;
  1822.    IF LOOPING THEN
  1823.       BEGIN
  1824.      C := UPPER(BUF[POINT]);
  1825.      IF ((C >='A' ) AND (C <= 'Z')) OR ((C >= '0') AND (C <= '9')) THEN
  1826.         BEGIN
  1827.            TYPTOKEN := NUMTOKEN;
  1828.            WHILE LOOPING DO
  1829.           BEGIN
  1830.              TC := TC+1;
  1831.              IF TC<9 THEN
  1832.             TOKEN[TC] := C;
  1833.              IF (TYPTOKEN = NUMTOKEN) AND(C >= '0') AND (C <= '9') THEN
  1834.             PNUM := 10*PNUM+ORD(C)-ORD('0')
  1835.               ELSE
  1836.             TYPTOKEN := ALFTOKEN;
  1837.              POINT := POINT+1;
  1838.              IF POINT<=ARS THEN
  1839.             BEGIN
  1840.                C := UPPER(BUF[POINT]);
  1841.                LOOPING := ((C >='A' ) AND (C <= 'Z')) OR ((C >= '0')
  1842.                       AND (C <= '9')) ;
  1843.             END
  1844.               ELSE
  1845.             LOOPING := FALSE;
  1846.           END { looping on name };
  1847.            IF TC > 8 THEN
  1848.           TC := 8;
  1849.         END { alfanumeric token }
  1850.      ELSE IF BUF[POINT] = '$' THEN
  1851.         BEGIN
  1852.            POINT := POINT + 1;
  1853.            TYPTOKEN := HEXTOKEN;
  1854.            LOOPING := POINT <= ARS;
  1855.            IF LOOPING = FALSE THEN
  1856.           TYPTOKEN := ERRTOKEN;
  1857.            WHILE LOOPING DO
  1858.           BEGIN
  1859.              C := UPPER(BUF[POINT]);
  1860.              IF (C >= '0') AND (C <= '9') THEN
  1861.             PNUM := 16*PNUM+ORD(C)-ORD('0')
  1862.              ELSE IF (C >= 'A') AND (C <= 'F') THEN
  1863.             PNUM := 16*PNUM+ORD(C)-ORD('A')+10
  1864.              ELSE IF C <> ' ' THEN
  1865.             BEGIN
  1866.                LOOPING := FALSE;
  1867.                TYPTOKEN := ERRTOKEN;
  1868.             END;
  1869.              POINT := POINT+1;
  1870.              IF POINT > ARS THEN
  1871.             LOOPING := FALSE;
  1872.           END { looping }
  1873.         END { hex token }
  1874.      ELSE IF POINT <= ARS THEN
  1875.         TYPTOKEN := ERRTOKEN
  1876.       END; { looping on find token }
  1877. END { PTOKEN };
  1878.  
  1879. PROCEDURE DOCALL(VAR C: HEADCALL);
  1880. { PTOKEN has already been called.  Anything but an
  1881.   ALFTOKEN is an error. }
  1882.  
  1883. VAR I: 0..255;
  1884. BEGIN
  1885.    IF (TYPTOKEN <> ALFTOKEN) OR (TC > 6) THEN
  1886.       OK := FALSE
  1887.     ELSE
  1888.       BEGIN
  1889.      FOR I := 1 TO 6 DO
  1890.         C.CALL[I] := ' ';  { blank it }
  1891.      C.SSID := CHR(0);
  1892.      FOR I := 1 TO TC DO
  1893.         C.CALL[I] := TOKEN[I];
  1894.      IF (POINT <= ARS) AND (BUF[POINT] = '-') THEN
  1895.         BEGIN
  1896.            POINT := POINT+1;
  1897.            PTOKEN(POINT);
  1898.            IF TYPTOKEN <> NUMTOKEN THEN
  1899.           OK := FALSE
  1900.            ELSE IF PNUM > 15 THEN
  1901.           OK := FALSE
  1902.         ELSE
  1903.           C.SSID := CHR(PNUM);
  1904.         END;
  1905.       END;
  1906. END { DOCALL };
  1907.  
  1908. PROCEDURE DOCLIST(VAR CARRAY: HEADTYPE; START: INTEGER; VAR I: INTEGER);
  1909.  
  1910. { PTOKEN has not been called.  Gets a list of call signs, separated
  1911.   by commas.  Return OK=FALSE if bad callsign encountered. Count of
  1912.   calls placed in CARRAY is returned in I. }
  1913.  
  1914. VAR LOOPING: BOOLEAN;
  1915. BEGIN
  1916.    OK := TRUE;
  1917.    I := START;
  1918.    LOOPING := TRUE;
  1919.    WHILE (I <= NUMHDCALL) AND OK AND LOOPING DO
  1920.       BEGIN
  1921.      PTOKEN(POINT);
  1922.      IF TYPTOKEN<>ALFTOKEN THEN
  1923.         OK := FALSE
  1924.      ELSE IF OK THEN
  1925.         BEGIN
  1926.            DOCALL(KLUDGE);
  1927.            CARRAY.CALLS[I] := KLUDGE;
  1928.            I := I + 1;
  1929.            IF (POINT <= ARS) AND (I <= NUMHDCALL) THEN
  1930.           BEGIN
  1931.              LOOPING := BUF[POINT] = ',';
  1932.              POINT := POINT + 1;
  1933.           END
  1934.         ELSE
  1935.           LOOPING := FALSE;
  1936.         END;
  1937.       END; { while looping }
  1938.    I := I - START;
  1939. END; { DOCLIST }
  1940.  
  1941. PROCEDURE PLIT;
  1942.  
  1943. VAR MATCH: BOOLEAN;
  1944.     LOOKING: BOOLEAN;
  1945.     I: 0..255;
  1946. BEGIN
  1947.    LOOKING := TRUE;
  1948.    LTYPE := SUCC(L_FNULL);
  1949.    WHILE (LTYPE<L_LNULL) AND LOOKING DO
  1950.       BEGIN
  1951.      MATCH := TRUE;
  1952.      I := 1;
  1953.      WHILE (I <= TC) AND MATCH DO
  1954.         BEGIN
  1955.            MATCH := TOKEN[I] = ROEXTVAR.LITTEXT[ORD(LTYPE),I];
  1956.            I := I + 1;
  1957.         END;
  1958.      IF MATCH THEN
  1959.         LOOKING := FALSE
  1960.       ELSE
  1961.         LTYPE := SUCC(LTYPE);
  1962.       END;
  1963.    IF LTYPE = L_YES THEN
  1964.       LTYPE := L_ON
  1965.    ELSE IF LTYPE = L_NO THEN
  1966.       LTYPE := L_OFF;
  1967. END;
  1968.  
  1969. PROCEDURE PCOM;
  1970.  
  1971. VAR MATCH: BOOLEAN;
  1972.     LOOKING: BOOLEAN;
  1973.     I: 0..255;
  1974. BEGIN
  1975.    LOOKING := TRUE;
  1976.    CTYPE := SUCC(C_FNULL);
  1977.    WHILE (CTYPE<C_LNULL) AND LOOKING DO
  1978.       BEGIN
  1979.      MATCH := TRUE;
  1980.      I := 1;
  1981.      WHILE (I <= TC) AND MATCH DO
  1982.         BEGIN
  1983.            MATCH := TOKEN[I] = ROEXTVAR.COMTEXT[ORD(CTYPE),I];
  1984.            I := I + 1;
  1985.         END;
  1986.      IF MATCH THEN
  1987.         LOOKING := FALSE
  1988.       ELSE
  1989.         CTYPE := SUCC(CTYPE);
  1990.       END;
  1991. END;
  1992.  
  1993. PROCEDURE WRITEDOL(I: INTEGER);
  1994.  
  1995. VAR J: INTEGER;
  1996. BEGIN
  1997.    I := I + PROMPTLEN-1;
  1998.    FOR J:=1 TO I DO
  1999.       WRITEBLK;
  2000.    WRITE1('$');
  2001.    WRITELAST;
  2002. END;
  2003.  
  2004. PROCEDURE WRITEEH(I: INTEGER);
  2005. BEGIN
  2006.    WRITEDOL(I);
  2007.    WRITE5(ROEXTVAR.MSG.EH,3);
  2008.    WRITELAST;
  2009. END;
  2010.  
  2011. PROCEDURE DISBOOL(BIT: BOOLEAN);
  2012. BEGIN
  2013.    IF BIT THEN
  2014.       WRITE5(ROEXTVAR.MSG.ON,3)
  2015.     ELSE
  2016.       WRITE5(ROEXTVAR.MSG.OFF,4)
  2017. END;
  2018.  
  2019.  
  2020. PROCEDURE SETBOOL(VAR BIT: BOOLEAN);
  2021.  
  2022. BEGIN { SETBOOL }
  2023.    PTOKEN(POINT);
  2024.    IF TYPTOKEN <> ALFTOKEN THEN
  2025.       OK := FALSE
  2026.    ELSE
  2027.       BEGIN
  2028.      PLIT;
  2029.      IF LTYPE = L_ON THEN
  2030.         BEGIN
  2031.            PTOKEN(POINT);
  2032.            IF TYPTOKEN <> NOTOKEN THEN
  2033.           OK := FALSE
  2034.         ELSE
  2035.           BEGIN
  2036.              WRITE5(ROEXTVAR.MSG.WAS,4);
  2037.              DISBOOL(BIT);
  2038.              WRITELAST;
  2039.              BIT := TRUE;
  2040.           END
  2041.         END
  2042.      ELSE IF LTYPE <> L_OFF THEN
  2043.         OK := FALSE
  2044.       ELSE
  2045.         BEGIN
  2046.            PTOKEN(POINT);
  2047.            IF TYPTOKEN <> NOTOKEN THEN
  2048.           OK := FALSE
  2049.         ELSE
  2050.           BEGIN
  2051.              WRITE5(ROEXTVAR.MSG.WAS,4);
  2052.              DISBOOL(BIT);
  2053.              WRITELAST;
  2054.              BIT := FALSE;
  2055.           END
  2056.         END;
  2057.       END;
  2058.    IF FALSE = OK THEN
  2059.       WRITEEH(PPOINT);
  2060. END; { SETBOOL }
  2061.  
  2062. PROCEDURE SETINT(VAR INT: INTEGER; LOW,HIGH: INTEGER);
  2063.  
  2064. VAR TI: INTEGER;
  2065. BEGIN
  2066.    PTOKEN(POINT);
  2067.    IF (TYPTOKEN <> NUMTOKEN) AND (TYPTOKEN <> HEXTOKEN) THEN
  2068.       OK := FALSE
  2069.    ELSE IF (PNUM < LOW) OR (PNUM > HIGH) THEN
  2070.       BEGIN
  2071.      WRITEDOL(PPOINT);
  2072.      WRITE20(ROEXTVAR.MSG.VALUEOUT,18);
  2073.      WRITELAST;
  2074.       END
  2075.     ELSE
  2076.       BEGIN
  2077.      TI := PNUM;
  2078.      PTOKEN(POINT);
  2079.      IF TYPTOKEN <> NOTOKEN THEN
  2080.         OK := FALSE
  2081.      ELSE
  2082.         BEGIN
  2083.            WRITE5(ROEXTVAR.MSG.WAS,4);
  2084.            DISINT(INT);
  2085.            WRITELAST;
  2086.            INT := TI;
  2087.         END
  2088.       END;
  2089.    IF FALSE = OK THEN
  2090.       WRITEEH(PPOINT);
  2091. END { SETINT };
  2092.  
  2093. PROCEDURE SETHEX(VAR INT: INTEGER; LOW,HIGH: INTEGER);
  2094.  
  2095. VAR TI: INTEGER;
  2096. BEGIN
  2097.    PTOKEN(POINT);
  2098.    IF (TYPTOKEN <> NUMTOKEN) AND (TYPTOKEN <> HEXTOKEN) THEN
  2099.       OK := FALSE
  2100.    ELSE IF (PNUM < LOW) OR (PNUM > HIGH) THEN
  2101.       BEGIN
  2102.      WRITEDOL(PPOINT);
  2103.      WRITE20(ROEXTVAR.MSG.VALUEOUT,18);
  2104.      WRITELAST;
  2105.       END
  2106.     ELSE
  2107.       BEGIN
  2108.      TI := PNUM;
  2109.      PTOKEN(POINT);
  2110.      IF TYPTOKEN <> NOTOKEN THEN
  2111.         OK := FALSE
  2112.       ELSE
  2113.         BEGIN
  2114.            WRITE5(ROEXTVAR.MSG.WAS,4);
  2115.            DISHEX(INT);
  2116.            WRITELAST;
  2117.            INT := TI;
  2118.         END
  2119.       END;
  2120.    IF FALSE = OK THEN
  2121.       WRITEEH(PPOINT);
  2122. END { SETHEX };
  2123.  
  2124. PROCEDURE SETCHR(VAR CH: CHAR; LOW,HIGH: INTEGER);
  2125.  
  2126. VAR TI: INTEGER;
  2127. BEGIN
  2128.    PTOKEN(POINT);
  2129.    IF (TYPTOKEN <> NUMTOKEN) AND (TYPTOKEN <> HEXTOKEN) THEN
  2130.       OK := FALSE
  2131.    ELSE IF (PNUM < LOW) OR (PNUM > HIGH) THEN
  2132.       BEGIN
  2133.      WRITEDOL(PPOINT);
  2134.      WRITE20(ROEXTVAR.MSG.VALUEOUT,18);
  2135.      WRITELAST;
  2136.       END
  2137.     ELSE
  2138.       BEGIN
  2139.      TI := PNUM;
  2140.      PTOKEN(POINT);
  2141.      IF TYPTOKEN <> NOTOKEN THEN
  2142.         OK := FALSE
  2143.       ELSE
  2144.         BEGIN
  2145.            WRITE5(ROEXTVAR.MSG.WAS,4);
  2146.            DISCHR(CH);
  2147.            WRITELAST;
  2148.            CH := CHR(TI);
  2149.         END
  2150.       END;
  2151.    IF FALSE = OK THEN
  2152.       WRITEEH(PPOINT);
  2153. END;
  2154.  
  2155.  
  2156. FUNCTION ACTIONCOM(ACT: COM_TYPE): BOOLEAN;
  2157. { This routine exists because HP Pascal doesn't like sets much }
  2158.  
  2159. BEGIN
  2160.    ACTIONCOM := (C_PERM = ACT) OR
  2161.         (C_DISCONNE = ACT) OR
  2162.         (C_DISPLAY = ACT ) OR
  2163.         (C_ID = ACT) OR
  2164.         (C_TRANS = ACT) OR
  2165.         (C_RESET = ACT) OR
  2166.         (C_CALIBRAT = ACT) OR
  2167.         (C_PROGRAM = ACT) OR
  2168.         (C_CONVERS = ACT);
  2169. END;
  2170.  
  2171. PROCEDURE DISPLAY(I: COM_TYPE);
  2172.  
  2173. BEGIN
  2174.    IF ACTIONCOM(I) = FALSE THEN
  2175.       BEGIN
  2176.      IF (I <> C_CONNECT) THEN
  2177.         WRITE8(ROEXTVAR.COMTEXT[ORD(I)],8);
  2178.      CASE I OF
  2179.         C_LNULL: ;
  2180.         C_ABAUD: DISINT (ROEXTVAR.ABAUD[ACX.ABAUD]);
  2181.         C_ABIT: DISINT (ACX.ABIT);
  2182.         C_AUTOLF: DISBOOL (ACX.AUTOLF);
  2183.         C_AWLEN: DISINT (ACX.AWLEN);
  2184.         C_AX25: DISBOOL (ACX.AX25);
  2185.         C_AXDELAY: DISINT (ACX.AXDLY);
  2186.         C_AXHANG: DISINT (ACX.AXHANG);
  2187.         C_BEACON:
  2188.            BEGIN
  2189.           IF ACX.BECEVY THEN
  2190.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_EVERY)],6)
  2191.            ELSE
  2192.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_AFTER)],6);
  2193.           WRITEINT(ACX.BECTIM);
  2194.            END;
  2195.         C_BKONDEL: DISBOOL (ACX.BKONDEL);
  2196.         C_BTEXT:
  2197.            BEGIN
  2198.           IF ACX.BECLEN > 0 THEN WRITE128(ACY.BECTXT,ACX.BECLEN-1);
  2199.            END;
  2200.         C_CALIBRAT: ;
  2201.         C_CANLINE: DISCHR (ACX.CLCHR);
  2202.         C_CANPAC: DISCHR (ACX.CPCHR);
  2203.         C_CMDTIME: DISINT (ACX.CMTIME);
  2204.         C_COMMAND: DISCHR (ACX.CMDCHR);
  2205.         C_CONMODE:
  2206.            IF ACX.CONMODE THEN
  2207.           WRITE8(ROEXTVAR.LITTEXT[ORD(L_CONVERS)],7)
  2208.         ELSE
  2209.           WRITE8(ROEXTVAR.LITTEXT[ORD(L_TRANS)],5);
  2210.         C_CONNECT:
  2211.            BEGIN
  2212.           WRITE15(ROEXTVAR.MSG.LINKSTATE,15);
  2213.           CASE LS OF
  2214.              LS1: WRITE15(ROEXTVAR.MSG.DISCON,12);
  2215.              LS2: WRITE20(ROEXTVAR.MSG.CONINPROG,19);
  2216.              LS3: WRITE20(ROEXTVAR.MSG.FRMRINPROG,16);
  2217.              LS4: WRITE20(ROEXTVAR.MSG.DISCINPROG,16);
  2218.              LS5:
  2219.             BEGIN
  2220.                WRITE15(ROEXTVAR.MSG.CONTO,13);
  2221.                DISCALL(CONCALL);
  2222.                IF CNCCNT>1 THEN
  2223.                   BEGIN
  2224.                  WRITEBLK;
  2225.                  WRITE8(ROEXTVAR.LITTEXT[ORD(L_VIA)],4);
  2226.                  DISCLIST(CNCCALL, RPCALLX, CNCCNT-1);
  2227.                   END;
  2228.             END;
  2229.           END { CASE LS };
  2230.            END { C_CONNECT };
  2231.         C_CONOK: DISBOOL (ACX.CONOK);
  2232.         C_CONVERS: ;
  2233.         C_CPACTIME: DISBOOL (ACX.CPT);
  2234.         C_CR: DISBOOL (ACX.CR);
  2235.         C_CWID: DISBOOL (ACX.CWID);
  2236.         C_DEBUG: DISCHR (ACX.DBGCHR);
  2237.         C_DELETE: DISBOOL (ACX.DELCHR);
  2238.         C_DIGIPEAT: DISBOOL (ACX.RPTOK);
  2239.         C_DISCONNE:  ;
  2240.         C_DISPLAY: ;
  2241.         C_DWAIT: DISINT (ACX.DWAIT);
  2242.         C_ECHO: DISBOOL (ACX.ECHO);
  2243.         C_ESCAPE: DISBOOL (ACX.ESCAPE);
  2244.         C_FLOW: DISBOOL (ACX.FLOW);
  2245.         C_FRACK: DISINT (ACX.IFTIME);
  2246.         C_FULLDUP: DISBOOL (ACX.FULLDUP);
  2247.         C_HBAUD: DISINT (ROEXTVAR.HBAUD[ACX.HBAUD]);
  2248.         C_ID: ;
  2249.         C_IDTEXT:
  2250.            BEGIN
  2251.           IF ACX.IDLEN > 0 THEN WRITE128(ACY.IDTXT,ACX.IDLEN-1);
  2252.            END;
  2253.         C_LCOK: DISBOOL (ACX.LCOK);
  2254.         C_LFADD: DISBOOL (ACX.LFADD);
  2255.         C_MAXFRAME: DISINT (ACX.KMAX);
  2256.         C_MONITOR: DISBOOL (ACX.MONON);
  2257.         C_MONALL: DISBOOL (ACX.MONALL);
  2258.         C_MONCON: DISBOOL (ACX.MONCON);
  2259.         C_MONTO:
  2260.            IF MON.TOLIST.CNT = 0 THEN
  2261.           IF MON.TOLIST.ALL THEN
  2262.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_ALL)],3)
  2263.            ELSE
  2264.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_NONE)],4)
  2265.         ELSE
  2266.           DISCLIST(MON.TOLIST.CALLS,1,MON.TOLIST.CNT);
  2267.         C_MONFROM:
  2268.            IF MON.FRLIST.CNT = 0 THEN
  2269.           IF MON.FRLIST.ALL THEN
  2270.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_ALL)],3)
  2271.            ELSE
  2272.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_NONE)],4)
  2273.         ELSE
  2274.           DISCLIST(MON.FRLIST.CALLS, 1, MON.FRLIST.CNT);
  2275.         C_MYCALL: DISCALL(ACX.MYCALL);
  2276.         C_MYVADR: DISCHR (ACX.VANID);
  2277.         C_NULLS: DISINT (ACX.NULLS);
  2278.         C_NUCR: DISBOOL (ACX.NUCR);
  2279.         C_NULF: DISBOOL (ACX.NULF);
  2280.         C_PACLEN: DISINT (ACX.PLEN);
  2281.         C_PACTIME:
  2282.            BEGIN
  2283.           IF ACX.PCEVY THEN
  2284.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_EVERY)],6)
  2285.            ELSE
  2286.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_AFTER)],6);
  2287.           DISINT (ACX.PCTIME);
  2288.            END;
  2289.         C_PARITY: DISINT (ACX.PARITY);
  2290.         C_PASS: DISCHR (ACX.PASCHR);
  2291.         C_PERM: ;
  2292.         C_PROGRAM: ;
  2293.         C_RETRY: DISINT (ACX.RETRY);
  2294.         C_REDISP: DISCHR (ACX.RDSCHR);
  2295.         C_RESET: ;
  2296.         C_SCREENL: DISINT (ACX.SCWID);
  2297.         C_SENDPAC: DISCHR (ACX.SPCHR);
  2298.         C_START: DISCHR (ACX.STRCHR);
  2299.         C_STOP: DISCHR (ACX.STPCHR);
  2300.         C_TRACE: DISHEX (TRACEDATA.NUMBR);
  2301.         C_TRANS: ;
  2302.         C_TXDELAY: DISINT (ACX.TXDLY);
  2303.         C_TXFLOW: DISBOOL (ACX.TXF);
  2304.         C_UNPROTO:
  2305.            BEGIN
  2306.           IF UCONLST.CALLS[FRCALLX].CALL[1] <> ' ' THEN
  2307.              DISCALL(UCONLST.CALLS[FRCALLX])
  2308.            ELSE
  2309.              WRITE8(ROEXTVAR.LITTEXT[ORD(L_NONE)],5);
  2310.           IF ACX.UCONCNT>1 THEN
  2311.              BEGIN
  2312.             WRITEBLK;
  2313.             WRITE8(ROEXTVAR.LITTEXT[ORD(L_VIA)],4);
  2314.             DISCLIST(UCONLST, RPCALLX, ACX.UCONCNT-1);
  2315.              END;
  2316.            END;
  2317.         C_VRPT: DISBOOL (ACX.VRPT);
  2318.         C_VDIGIPEA: DISBOOL (ACX.VANCDP);
  2319.         C_XFLOW: DISBOOL (ACX.XFLOW);
  2320.         C_XMITOK: DISBOOL (ACX.XMITOK);
  2321.         C_XOFF: DISCHR (ACX.XFFCHR);
  2322.         C_XON: DISCHR (ACX.XONCHR);
  2323.      END { CASE on CTYPE };
  2324.      WRITELAST;
  2325.       END;
  2326. END;
  2327.  
  2328. PROCEDURE PCLIST(VAR L: MONLIST);
  2329. { parse MONFROM and MONTO commands }
  2330.  
  2331. VAR SV: INTEGER;
  2332. BEGIN
  2333.    SV := POINT;
  2334.    PTOKEN(POINT);
  2335.    OK := TRUE;
  2336.    IF TYPTOKEN <> ALFTOKEN THEN
  2337.       OK := FALSE
  2338.     ELSE
  2339.       BEGIN
  2340.      PLIT;
  2341.      IF LTYPE = L_ALL THEN
  2342.         BEGIN
  2343.            L.ALL := TRUE;
  2344.            L.CNT := 0;
  2345.         END
  2346.      ELSE IF LTYPE = L_NONE THEN
  2347.         BEGIN
  2348.            L.ALL := FALSE;
  2349.            L.CNT := 0;
  2350.         END
  2351.       ELSE
  2352.         BEGIN
  2353.            POINT := SV;
  2354.            DOCLIST(L.CALLS, 1, SV);
  2355.            L.CNT := SV;
  2356.         END
  2357.       END;
  2358. END;
  2359.  
  2360. PROCEDURE EVRYAFTR(VAR EVAF: BOOLEAN; VAR EATIME: INTEGER; MAXT: INTEGER);
  2361.  
  2362. BEGIN { EVRYAFTR }
  2363.    TBIT := EVAF;
  2364.    PTOKEN(POINT);
  2365.    IF TYPTOKEN = ALFTOKEN THEN
  2366.       BEGIN
  2367.      PLIT;
  2368.      IF (LTYPE <> L_EVERY) AND (LTYPE <> L_AFTER) THEN
  2369.         OK := FALSE
  2370.       ELSE
  2371.         BEGIN
  2372.            EVAF := TRUE;
  2373.            IF LTYPE = L_AFTER THEN
  2374.           EVAF := FALSE;
  2375.            PTOKEN(POINT);
  2376.         END;
  2377.       END;
  2378.    IF (TYPTOKEN <> NUMTOKEN) AND (TYPTOKEN <> HEXTOKEN) THEN
  2379.       OK := FALSE;
  2380.    IF OK THEN
  2381.       IF PNUM > MAXT THEN
  2382.      BEGIN
  2383.         WRITEDOL(PPOINT);
  2384.         WRITE20(ROEXTVAR.MSG.VALUEOUT,20);
  2385.         WRITELAST;
  2386.      END
  2387.        ELSE
  2388.      BEGIN
  2389.         WRITE5(ROEXTVAR.MSG.WAS,4);
  2390.         IF TBIT THEN
  2391.            WRITE8(ROEXTVAR.LITTEXT[ORD(L_EVERY)],6)
  2392.          ELSE
  2393.            WRITE8(ROEXTVAR.LITTEXT[ORD(L_AFTER)],6);
  2394.         WRITEINT(EATIME);
  2395.         WRITELAST;
  2396.         EATIME := PNUM;
  2397.      END
  2398. END; { EVRYAFTR }
  2399.  
  2400. PROCEDURE GETTXT(VAR TEXT: CH128; VAR LENGTH: INTEGER);
  2401.  
  2402. BEGIN
  2403.    WRITE5(ROEXTVAR.MSG.WAS,4);
  2404.    IF LENGTH > 0 THEN WRITE128(TEXT,LENGTH)
  2405.    ELSE WRITELAST;
  2406.    I := 1;
  2407.    WHILE ((POINT <= ARS) AND (I < 128)) DO
  2408.       BEGIN
  2409.      TEXT[I] := BUF[POINT];
  2410.      POINT := POINT + 1;
  2411.      I := I + 1;
  2412.       END;
  2413.    LENGTH := I;
  2414.    TEXT[I] := CHR(13);
  2415. END;
  2416.  
  2417. PROCEDURE SETBAUD(VAR INT:INTEGER; BAUD:BAUDTYPE);
  2418.  
  2419. VAR I: INTEGER;
  2420.  
  2421. BEGIN
  2422.    PTOKEN(POINT);
  2423.    IF (TYPTOKEN <> NUMTOKEN) AND (TYPTOKEN <> HEXTOKEN) THEN
  2424.       OK := FALSE
  2425.     ELSE
  2426.       BEGIN
  2427.      I := 0;
  2428.      WHILE ((PNUM <> BAUD[I]) AND (I < 16)) DO
  2429.         I := I+1;
  2430.      IF I = 16 THEN
  2431.         OK := FALSE
  2432.       ELSE
  2433.         BEGIN
  2434.            WRITE5(ROEXTVAR.MSG.WAS,4);
  2435.            DISINT(BAUD[INT]);
  2436.            WRITELAST;
  2437.            INT := I;
  2438.         END
  2439.       END;
  2440.    IF OK = FALSE THEN
  2441.       WRITEEH(PPOINT);
  2442. END;
  2443.  
  2444. PROCEDURE DO_DISPLAY;
  2445.  
  2446. VAR CC: COM_TYPE;
  2447.  
  2448. BEGIN
  2449.    PTOKEN(POINT);
  2450.    IF TYPTOKEN = NOTOKEN THEN
  2451.       BEGIN
  2452.      FOR CC := SUCC(C_FNULL) TO PRED(C_LNULL) DO
  2453.         DISPLAY(CC);
  2454.       END
  2455.    ELSE IF TYPTOKEN = ALFTOKEN THEN
  2456.       BEGIN
  2457.      PLIT;
  2458.      IF LTYPE = L_LINK THEN
  2459.         BEGIN
  2460.            DISPLAY(C_AX25);
  2461.            DISPLAY(C_CONMODE);
  2462.            DISPLAY(C_CONOK);
  2463.            DISPLAY(C_CR);
  2464.            DISPLAY(C_DIGIPEAT);
  2465.            DISPLAY(C_FULLDUP);
  2466.            DISPLAY(C_HBAUD);
  2467.            DISPLAY(C_LFADD);
  2468.            DISPLAY(C_MAXFRAME);
  2469.            DISPLAY(C_PACLEN);
  2470.            DISPLAY(C_RETRY);
  2471.            DISPLAY(C_TRACE);
  2472.            DISPLAY(C_VDIGIPEA);
  2473.            DISPLAY(C_VRPT);
  2474.            DISPLAY(C_XMITOK);
  2475.         END
  2476.      ELSE IF LTYPE = L_ID THEN
  2477.         BEGIN
  2478.            DISPLAY(C_BEACON);
  2479.            DISPLAY(C_BTEXT);
  2480.            DISPLAY(C_CWID);
  2481.            DISPLAY(C_IDTEXT);
  2482.            DISPLAY(C_MYCALL);
  2483.            DISPLAY(C_MYVADR);
  2484.            DISPLAY(C_UNPROTO);
  2485.         END
  2486.      ELSE IF LTYPE = L_MONITOR THEN
  2487.         BEGIN
  2488.            DISPLAY(C_MONITOR);
  2489.            DISPLAY(C_MONALL);
  2490.            DISPLAY(C_MONCON);
  2491.            DISPLAY(C_MONFROM);
  2492.            DISPLAY(C_MONTO);
  2493.         END
  2494.      ELSE IF LTYPE = L_TERMINAL THEN
  2495.         BEGIN
  2496.            DISPLAY(C_ABAUD);
  2497.            DISPLAY(C_ABIT);
  2498.            DISPLAY(C_AUTOLF);
  2499.            DISPLAY(C_AWLEN);
  2500.            DISPLAY(C_BKONDEL);
  2501.            DISPLAY(C_ECHO);
  2502.            DISPLAY(C_ESCAPE);
  2503.            DISPLAY(C_FLOW);
  2504.            DISPLAY(C_LCOK);
  2505.            DISPLAY(C_NULLS);
  2506.            DISPLAY(C_NUCR);
  2507.            DISPLAY(C_NULF);
  2508.            DISPLAY(C_PARITY);
  2509.            DISPLAY(C_SCREENL);
  2510.            DISPLAY(C_TXFLOW);
  2511.            DISPLAY(C_XFLOW);
  2512.         END
  2513.      ELSE IF LTYPE = L_TIMING THEN
  2514.         BEGIN
  2515.            DISPLAY(C_AXDELAY);
  2516.            DISPLAY(C_AXHANG);
  2517.            DISPLAY(C_CMDTIME);
  2518.            DISPLAY(C_CPACTIME);
  2519.            DISPLAY(C_DWAIT);
  2520.            DISPLAY(C_FRACK);
  2521.            DISPLAY(C_PACTIME);
  2522.            DISPLAY(C_TXDELAY);
  2523.         END
  2524.      ELSE IF LTYPE = L_CHAR THEN
  2525.         BEGIN
  2526.            DISPLAY(C_CANLINE);
  2527.            DISPLAY(C_CANPAC);
  2528.            DISPLAY(C_COMMAND);
  2529.            DISPLAY(C_DEBUG);
  2530.            DISPLAY(C_DELETE);
  2531.            DISPLAY(C_PASS);
  2532.            DISPLAY(C_REDISP);
  2533.            DISPLAY(C_SENDPAC);
  2534.            DISPLAY(C_START);
  2535.            DISPLAY(C_STOP);
  2536.            DISPLAY(C_XON);
  2537.            DISPLAY(C_XOFF);
  2538.         END
  2539.       ELSE OK := FALSE;
  2540.       END
  2541.     ELSE OK := FALSE;
  2542.    IF OK = FALSE THEN WRITEEH(PPOINT);
  2543. END;  { add more code here /*N*/ }
  2544.  
  2545. PROCEDURE DOIT;
  2546.  
  2547. VAR
  2548.     CCTYPE: COM_TYPE;
  2549.     II: INTEGER;
  2550.  
  2551. BEGIN
  2552.    CASE CTYPE OF
  2553.       C_LNULL:
  2554.      BEGIN
  2555.         OK := FALSE;
  2556.         EH := TRUE;
  2557.      END;
  2558.       C_ABAUD: SETBAUD (ACX.ABAUD,ROEXTVAR.ABAUD);
  2559.       C_ABIT: SETINT (ACX.ABIT,1,2);
  2560.       C_AUTOLF: SETBOOL (ACX.AUTOLF);
  2561.       C_AWLEN: SETINT(ACX.AWLEN,7,8);
  2562.       C_AX25:
  2563.      BEGIN
  2564.         IF LS <> LS1 THEN
  2565.            BEGIN
  2566.           WRITE20(ROEXTVAR.MSG.NOTWHILE,19);
  2567.           WRITELAST;
  2568.           OK := FALSE;
  2569.            END
  2570.          ELSE
  2571.            SETBOOL(ACX.AX25);
  2572.      END;
  2573.       C_AXDELAY: SETINT (ACX.AXDLY,0,15);
  2574.       C_AXHANG: SETINT (ACX.AXHANG,0,15);
  2575.       C_BEACON:
  2576.      BEGIN { BEACON }
  2577.         EVRYAFTR(ACX.BECEVY,ACX.BECTIM,255);
  2578.         IF OK THEN
  2579.            BEGIN
  2580.  
  2581.      { Now see if we are (re)starting the clock, or stopping it. }
  2582.           IF ACX.BECTIM = 0 THEN
  2583.              ACX.TBEACON.RUNNING := FALSE
  2584.            ELSE
  2585.              BEGIN
  2586.             ACX.TBEACON.RUNNING := TRUE;
  2587.             ACX.TBEACON.TSTOP :=
  2588.                ACX.TICKER + ACX.BECTIM*ROEXTVAR.TICKSPS*10;
  2589.              END;
  2590.            END
  2591.          ELSE
  2592.            EH := TRUE;
  2593.      END; { BEACON }
  2594.       C_BKONDEL: SETBOOL(ACX.BKONDEL);
  2595.       C_BTEXT: GETTXT(ACY.BECTXT,ACX.BECLEN);
  2596.       C_CALIBRAT: CALIBR;
  2597.       C_CANLINE: SETCHR (ACX.CLCHR,0,127);
  2598.       C_CANPAC: SETCHR (ACX.CPCHR,0,127);
  2599.       C_CMDTIME: SETINT(ACX.CMTIME,0,15);
  2600.       C_COMMAND: SETCHR (ACX.CMDCHR,0,127);
  2601.       C_CONMODE:
  2602.      BEGIN { CONMODE }
  2603.         PTOKEN(POINT);
  2604.         IF TYPTOKEN <> ALFTOKEN THEN
  2605.            BEGIN
  2606.           OK := FALSE;
  2607.           EH := TRUE;
  2608.            END
  2609.          ELSE
  2610.            BEGIN { alpha }
  2611.           PLIT;
  2612.           TBIT := ACX.CONMODE;
  2613.           IF (LTYPE <> L_CONVERS) AND (LTYPE <> L_TRANS) THEN
  2614.              BEGIN
  2615.             OK := FALSE;
  2616.             EH := TRUE;
  2617.              END
  2618.            ELSE
  2619.              BEGIN
  2620.             ACX.CONMODE := TRUE;
  2621.             IF LTYPE = L_TRANS THEN
  2622.                ACX.CONMODE := FALSE;
  2623.             WRITE5(ROEXTVAR.MSG.WAS,4);
  2624.             IF TBIT THEN
  2625.                WRITE8(ROEXTVAR.LITTEXT[ORD(L_CONVERS)],7)
  2626.              ELSE
  2627.                WRITE8(ROEXTVAR.LITTEXT[ORD(L_TRANS)],5);
  2628.             WRITELAST;
  2629.              END;
  2630.            END; { alpha }
  2631.      END; { CONMODE }
  2632.       C_CONNECT:
  2633.      IF LS <> LS1 THEN
  2634.         BEGIN
  2635.            WRITE15(ROEXTVAR.MSG.CANTCON,15);
  2636.            DISPLAY(C_CONNECT);
  2637.            OK := FALSE;
  2638.         END
  2639.       ELSE
  2640.         BEGIN { LS=LS1 }
  2641.            CNCCNT := 1;
  2642.            NMODEF2 := ACX.CONMODE;
  2643.            PTOKEN(POINT); { Get first token after command keyword }
  2644.            DOCALL(KLUDGE); { Get first callsign }
  2645.  
  2646.      { Yes, I am really putting the evenrual 'TO' call in the array
  2647.        with an index of FRCALLX.  What I'm really doing is building
  2648.        a pseudo incoming SABM frame for Dave's code.  I'm told that
  2649.        this makes things easy for him. }
  2650.            IF OK THEN
  2651.           BEGIN { tocall ok }
  2652.              CNCCALL.CALLS[FRCALLX] := KLUDGE;
  2653.              PTOKEN(POINT);  { next token }
  2654.              IF TYPTOKEN=ALFTOKEN THEN
  2655.             PLIT
  2656.               ELSE IF TYPTOKEN <> NOTOKEN THEN
  2657.             OK := FALSE;
  2658.           END; { tocall ok }
  2659.            IF OK AND (TYPTOKEN=ALFTOKEN) THEN
  2660.           IF LTYPE = L_VIA THEN
  2661.              BEGIN  { parse digipeaters }
  2662.             DOCLIST(CNCCALL,RPCALLX,I);
  2663.             IF OK THEN
  2664.                BEGIN
  2665.                   CNCCNT := I+1;
  2666.                   PTOKEN(POINT); { setup next token }
  2667.                   IF TYPTOKEN = ALFTOKEN THEN
  2668.                  PLIT
  2669.                    ELSE IF TYPTOKEN <> NOTOKEN THEN
  2670.                  OK := FALSE;
  2671.                END;
  2672.              END; { digipeaters }
  2673.            IF OK AND (TYPTOKEN = ALFTOKEN) THEN
  2674.           IF LTYPE = L_CONVERS THEN
  2675.              NMODEF2 := TRUE
  2676.           ELSE IF LTYPE = L_TRANS THEN
  2677.              NMODEF2 := FALSE
  2678.            ELSE
  2679.              OK := FALSE;
  2680.            IF FALSE = OK THEN
  2681.           EH := TRUE
  2682.         ELSE
  2683.           CMPRS := F_CON;
  2684.         END; { LS = LS1 }
  2685.      { end CONNECT }
  2686.       C_CONOK: SETBOOL (ACX.CONOK);
  2687.       C_CONVERS:
  2688.      BEGIN
  2689.         ACX.MODEF2 := TRUE;
  2690.         ACX.MODEF1 := FALSE;
  2691.         SETMOD; { tell LLR - mode change }
  2692.      END;
  2693.       C_CPACTIME: SETBOOL (ACX.CPT);
  2694.       C_CR: SETBOOL (ACX.CR);
  2695.       C_CWID: SETBOOL (ACX.CWID);
  2696.       C_DEBUG: SETCHR (ACX.DBGCHR,0,127);
  2697.       C_DELETE: SETBOOL (ACX.DELCHR);
  2698.       C_DIGIPEAT: SETBOOL (ACX.RPTOK);
  2699.       C_DISCONNE:
  2700.      IF LS = LS1 THEN
  2701.         BEGIN
  2702.            WRITE20(ROEXTVAR.MSG.CANTDISC,18);
  2703.            DISPLAY(C_CONNECT);
  2704.            OK := FALSE;
  2705.         END
  2706.       ELSE
  2707.         BEGIN
  2708.            PTOKEN(POINT);
  2709.            IF TYPTOKEN = NOTOKEN THEN
  2710.           CMPRS := F_DISC
  2711.         ELSE
  2712.           BEGIN
  2713.              OK := FALSE;
  2714.              EH := TRUE;
  2715.           END;
  2716.      END; { DISCONNECT }
  2717.       C_DISPLAY: DO_DISPLAY;
  2718.       C_DWAIT: SETINT (ACX.DWAIT,0,15);
  2719.       C_ECHO: SETBOOL (ACX.ECHO);
  2720.       C_ESCAPE: SETBOOL (ACX.ESCAPE);
  2721.       C_FLOW: SETBOOL (ACX.FLOW);
  2722.       C_FRACK: SETINT (ACX.IFTIME,0,15);
  2723.       C_FULLDUP: SETBOOL (ACX.FULLDUP);
  2724.       C_HBAUD: SETBAUD (ACX.HBAUD, ROEXTVAR.HBAUD);
  2725.       C_ID: CWID;  { send cw ID }
  2726.       C_IDTEXT: GETTXT(ACY.IDTXT,ACX.IDLEN);
  2727.       C_LCOK: SETBOOL (ACX.LCOK);
  2728.       C_LFADD: SETBOOL (ACX.LFADD);
  2729.       C_MAXFRAME: SETINT (ACX.KMAX,1,7);
  2730.       C_MONITOR: SETBOOL (ACX.MONON);
  2731.       C_MONALL: SETBOOL(ACX.MONALL);
  2732.       C_MONCON: SETBOOL (ACX.MONCON);
  2733.       C_MONTO:
  2734.      BEGIN
  2735.         PCLIST(MON.TOLIST);
  2736.         IF OK THEN
  2737.            ACX.MONTO := MON.TOLIST.ALL
  2738.          ELSE
  2739.            EH := TRUE;
  2740.      END;
  2741.       C_MONFROM:
  2742.      BEGIN
  2743.         PCLIST(MON.FRLIST);
  2744.         IF OK THEN
  2745.            ACX.MONFROM := MON.FRLIST.ALL
  2746.         ELSE
  2747.            EH := TRUE;
  2748.      END;
  2749.       C_MYCALL:
  2750.      BEGIN
  2751.         PTOKEN(POINT);
  2752.         DOCALL(ACX.MYCALL);
  2753.         IF FALSE = OK THEN
  2754.            EH := TRUE;
  2755.      END;
  2756.       C_MYVADR: SETCHR (ACX.VANID,0,31);
  2757.       C_NULLS: SETINT (ACX.NULLS,0,31);
  2758.       C_NUCR: SETBOOL (ACX.NUCR);
  2759.       C_NULF: SETBOOL (ACX.NULF);
  2760.       C_PACLEN: SETINT (ACX.PLEN,1,256);
  2761.       C_PACTIME:
  2762.      BEGIN
  2763.         EVRYAFTR(ACX.PCEVY,ACX.PCTIME,15);
  2764.         IF FALSE = OK THEN
  2765.            EH := TRUE;
  2766.      END;
  2767.       C_PARITY: SETINT (ACX.PARITY,0,4);
  2768.       C_PASS: SETCHR (ACX.PASCHR,0,127);
  2769.       C_PERM: PUTNVB; { write NOVRAM and burn }
  2770.       C_PROGRAM: PROGRM;
  2771.       C_REDISP: SETCHR (ACX.RDSCHR,0,127);
  2772.       C_RESET: RESET1;
  2773.       C_RETRY: SETINT (ACX.RETRY,0,15);
  2774.       C_SCREENL: SETINT (ACX.SCWID,0,255);
  2775.       C_SENDPAC: SETCHR (ACX.SPCHR,0,127);
  2776.       C_START: SETCHR (ACX.STRCHR,0,127);
  2777.       C_STOP: SETCHR(ACX.STPCHR,0,127);
  2778.       C_TRACE: SETHEX (TRACEDATA.NUMBR,-32767,32767);
  2779.       C_TRANS:
  2780.      BEGIN
  2781.         ACX.MODEF2 := FALSE;
  2782.         ACX.MODEF1 := FALSE;
  2783.         SETMOD; { tell LLR - mode change }
  2784.      END;
  2785.       C_TXDELAY: SETINT (ACX.TXDLY,1,16);
  2786.       C_TXFLOW: SETBOOL (ACX.TXF);
  2787.       C_UNPROTO:
  2788.      BEGIN { UNPROTO }
  2789.         PTOKEN(POINT);
  2790.         IF TYPTOKEN <> ALFTOKEN THEN
  2791.            BEGIN
  2792.           OK := FALSE;
  2793.           EH := TRUE;
  2794.            END
  2795.          ELSE
  2796.            BEGIN { alpha }
  2797.           PLIT;
  2798.           IF LTYPE = L_NONE THEN
  2799.              BEGIN
  2800.             ACX.UCONCNT := 0;
  2801.             FOR II := 1 TO 6 DO
  2802.                UCONLST.CALLS[FRCALLX].CALL[II] := ' ';
  2803.             UCONLST.CALLS[FRCALLX].SSID := CHR(0);
  2804.              END
  2805.            ELSE
  2806.              BEGIN { parse to call }
  2807.             DOCALL(KLUDGE);
  2808.             IF OK THEN
  2809.                BEGIN
  2810.                   UCONLST.CALLS[FRCALLX] := KLUDGE;
  2811.                   ACX.UCONCNT := 1;
  2812.                END
  2813.              ELSE
  2814.                EH := TRUE;
  2815.              END; { parse to call }
  2816.           PTOKEN(POINT);
  2817.           IF TYPTOKEN <> NOTOKEN THEN
  2818.              BEGIN { parse digipeaters }
  2819.             PLIT;
  2820.             IF TYPTOKEN <> ALFTOKEN THEN
  2821.                OK := FALSE
  2822.              ELSE
  2823.                IF LTYPE <> L_VIA THEN
  2824.                   OK := FALSE;
  2825.             IF OK THEN
  2826.                DOCLIST(UCONLST,RPCALLX,I);
  2827.             IF OK THEN
  2828.                ACX.UCONCNT := I + 1
  2829.              ELSE
  2830.                EH := TRUE;
  2831.              END; { parse digipeaters }
  2832.            END; { alpha }
  2833.      END; { UNPROTO }
  2834.       C_VRPT: SETBOOL (ACX.VRPT);
  2835.       C_VDIGIPEA: SETBOOL (ACX.VANCDP);
  2836.       C_XFLOW: SETBOOL (ACX.XFLOW);
  2837.       C_XMITOK: SETBOOL (ACX.XMITOK);
  2838.       C_XOFF: SETCHR (ACX.XFFCHR,0,127);
  2839.       C_XON: SETCHR (ACX.XONCHR,0,127);
  2840.    END { CASE on CTYPE };
  2841. END;
  2842.  
  2843. BEGIN { COMPARSE }
  2844.  
  2845.    GETCMD(BUF,ARS); { Get command line, no CR, Dave won't call if ARS=0 }
  2846.    CMPRS := F_NULL;
  2847.    OK := TRUE;
  2848.    EH := FALSE;
  2849.    PTOKEN(1);
  2850.    IF (TYPTOKEN <> ALFTOKEN) AND (TYPTOKEN <> NOTOKEN) THEN
  2851.       BEGIN
  2852.      OK := FALSE;
  2853.      WRITEEH(PPOINT);
  2854.       END;
  2855.    IF TYPTOKEN = ALFTOKEN THEN
  2856.       BEGIN { find command }
  2857.      PCOM;
  2858.      IF CTYPE = C_LNULL THEN
  2859.         BEGIN
  2860.            OK := FALSE;
  2861.            EH := TRUE;
  2862.         END
  2863.       ELSE
  2864.         IF NOT ACTIONCOM(CTYPE) AND NOT SP_SKIP(POINT) THEN
  2865.            DISPLAY(CTYPE)
  2866.          ELSE
  2867.            DOIT;
  2868.      IF FALSE = OK THEN
  2869.         BEGIN
  2870.            IF EH THEN
  2871.           WRITEEH(PPOINT);
  2872.         END
  2873.       ELSE
  2874.         BEGIN
  2875.            PTOKEN(POINT);
  2876.            IF TYPTOKEN <> NOTOKEN THEN
  2877.           BEGIN
  2878.              WRITEDOL(PPOINT);
  2879.              WRITE15(ROEXTVAR.MSG.IGNORED,13);
  2880.              WRITELAST;
  2881.           END;
  2882.            PUTNV; { tell Margaret to repack NOVRAM }
  2883.         END;
  2884.       END; { find command }
  2885.    IF ACX.MODEF1 THEN
  2886.       WRITE5(ROEXTVAR.MSG.PROMPT,4);
  2887.    COMPARSE := CMPRS;
  2888. END { COMPARSE };
  2889.  
  2890. PROCEDURE REALAX25;
  2891.  
  2892. BEGIN { REALAX25 }
  2893.    ACX.UCONCNT := 1;
  2894.    UCONLST.CALLS[FRCALLX].CALL := ROEXTVAR.CQ;
  2895.    UCONLST.CALLS[FRCALLX].SSID := CHR(0);
  2896.    LS := LS1;
  2897.    TRACEDATA.BITS := [DUMPFRMR]; { dump FRMRs in hex }
  2898.    MON.TOLIST.ALL := ACX.MONTO;  { init from NOVRAM }
  2899.    MON.FRLIST.ALL := ACX.MONFROM; { ditto }
  2900.  
  2901. { Parse command input.    Return with the appropriate FTYPE }
  2902.  
  2903. { kludge, but it works }
  2904.    IF ACX.RETRY>0 THEN
  2905.       XRETRY := ACX.RETRY
  2906.     ELSE
  2907.       XRETRY := -1;
  2908.    RETRYCNT := XRETRY;
  2909.    REPEAT { forever }
  2910.       LAPBPROC(F_NULL);
  2911.       IF ACX.CBPRES THEN
  2912.      BEGIN { process command }
  2913.         PARSERES := COMPARSE;
  2914.  
  2915. { kludge, but it works }
  2916.         IF ACX.RETRY>0 THEN
  2917.            XRETRY := ACX.RETRY
  2918.          ELSE
  2919.            XRETRY := -1;
  2920.         LAPBPROC(PARSERES);
  2921.      END { stuff to parse };
  2922.    UNTIL FALSE;
  2923. END { REALAX25 };
  2924. BEGIN { AX25MAIN }
  2925. END { AX25MAIN }.
  2926.